使用 Dockerfile 定制镜像详解

使用 Dockerfile 定制镜像详解

  • 1.Dockerfile
    • FROM 指定基础镜像
    • RUN 执行命令
    • 构建镜像
  • 2.COPY 复制文件
  • 3.ADD 更高级的复制文件
  • 4.CMD 容器启动命令
  • 5.ENTRYPOINT 入口点
  • 6.ENV 设置环境变量
  • 7.ARG 构建参数
  • 8.VOLUME 定义匿名卷
  • 9.EXPOSE 暴露端口
  • 10.WORKDIR 指定工作目录
  • 11.USER 指定当前用户
  • 12.LABEL 为镜像添加元数据
  • 13.SHELL 指令

1.Dockerfile

Dockerfile 是一个文本文件,其内包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建

还以之前定制 nginx 镜像为例,这次我们使用 Dockerfile 来定制:

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基础镜像

FROM 就是指定 基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令

在 Docker Hub 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 nginx、redis、mongo、mysql、httpd、php、tomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 node、openjdk、python、ruby、golang 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像:

FROM scratch
...

如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在

RUN 执行命令

RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:

  • shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式

Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。所以在执行多条命令的场景下,最好遵守如下的规范:

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉

构建镜像

1、编写dockerfile

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

2、在 Dockerfile 文件所在目录执行

docker build -t nginx .

在这里插入图片描述

从命令的输出结果中,我们可以清晰的看到镜像的构建过程

镜像构建上下文中的坑🕳

当我们进行镜像构建的时候,并非所有定制都会通过 RUN 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 COPY 指令、ADD 指令等。而 docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢?

这就引入了上下文的概念。当构建的时候,用户会指定构建镜像上下文的路径,docker build 命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件

有些初学者在发现 COPY /opt/xxxx /app 不工作后,于是干脆将 Dockerfile 放到了硬盘根目录去构建,结果发现 docker build 执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让 docker build 打包整个硬盘,这显然是使用错误

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的


2.COPY 复制文件

COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。比如:

COPY package.json /usr/src/app/

使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等

在使用该指令的时候还可以加上 --chown=<user>:<group> 选项来改变文件的所属用户及所属组:

COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/

如果源路径为文件夹,复制的时候不是直接复制该文件夹,而是将文件夹中的内容复制到目标路径


3.ADD 更高级的复制文件

ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能

比如 <源路径> 可以是一个 URL,这种情况下,Docker 引擎会试图去下载这个链接的文件放到 <目标路径> 去。下载后的文件权限自动设置为 600

如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去

Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合

ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢


4.CMD 容器启动命令

在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的

CMD 指令的格式和 RUN 相似,也是两种格式:

  • shell 格式:CMD <命令>
  • exec 格式:CMD [“可执行文件”, “参数1”, “参数2”…]

在指令格式上,一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 ",而不要使用单引号

如果使用 shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:

CMD echo $HOME

在实际执行中,会将其变更为:

CMD [ "sh", "-c", "echo $HOME" ]

坑🕳:容器执行后就立即退出了

容器内没有后台服务的概念。一些初学者将 CMD 写为:

CMD service nginx start

然后发现容器执行后就立即退出了。这就是因为没有搞明白前台、后台的概念

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西

而使用 service nginx start 命令,则是希望 init 系统以后台守护进程的形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [ "sh", "-c", "service nginx start"],因此主进程实际上是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 作为主进程退出了,自然就会令容器退出

正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

CMD ["nginx", "-g", "daemon off;"]

5.ENTRYPOINT 入口点

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数

那么有了 CMD 后,为什么还要有 ENTRYPOINT 呢?

1、场景一:让镜像变成像命令一样使用

假设我们需要一个得知自己当前公网 IP 的镜像

FROM ubuntu:18.04
RUN apt-get update \
    && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://myip.ipip.net" ]

构建镜像:

docker build -t myip .

我们来尝试直接使用 docker run myip -i

$ docker run myip
当前 IP:xx.xx.xx.xx 来自:纽约市 联信

$ docker run myip -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 22 Nov 2016 05:12:40 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
X-Cache: MISS from cache-2
X-Cache-Lookup: MISS from cache-2:80
X-Cache: MISS from proxy-2_6
Transfer-Encoding: chunked
Via: 1.1 cache-2:80, 1.1 proxy-2_6:8006
Connection: keep-alive

当前 IP:xx.xx.xx.xx 来自:纽约市 联信

当存在 ENTRYPOINT 后,CMD 的内容将会作为参数传给 ENTRYPOINT,而这里 -i 就是新的 CMD,因此会作为参数传给 curl,从而达到了我们预期的效果

2、场景二:应用运行前的准备工作

mysql 类的数据库,可能需要一些数据库配置、初始化的工作,这些工作要在最终的 mysql 服务器运行之前解决

此外,可能希望避免使用 root 用户去启动服务,从而提高安全性,而在启动服务前还需要以 root 身份执行一些必要的准备工作,最后切换到服务用户身份启动服务。或者除了服务外,其它命令依旧可以使用 root 身份执行,方便调试等

这些准备工作是和容器 CMD 无关的,无论 CMD 为什么,都需要事先进行一个预处理的工作。这种情况下,可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 <CMD>)作为命令,在脚本最后执行。比如官方镜像 redis 中就是这么做的:

FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD [ "redis-server" ]

6.ENV 设置环境变量

格式有两种:

  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...

定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。比如在官方 node 镜像 Dockerfile 中,就有类似这样的代码:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
  && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
  && grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
  && tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
  && rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
  && ln -s /usr/local/bin/node /usr/local/bin/nodejs

在这里先定义了环境变量 NODE_VERSION,其后的 RUN 这层里,多次使用 $NODE_VERSION 来进行操作定制。可以看到,将来升级镜像构建版本的时候,只需要更新 7.2.0 即可,Dockerfile 构建维护变得更轻松了

通过环境变量,我们可以让一份 Dockerfile 制作更多的镜像,只需使用不同的环境变量即可


7.ARG 构建参数

格式:ARG <参数名>[=<默认值>]

构建参数和 ENV 的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的

灵活的使用 ARG 指令,能够在不修改 Dockerfile 的情况下,构建出不同的镜像

ARG 指令有生效范围,如果在 FROM 指令之前指定,那么只能用于 FROM 指令中:

ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
RUN set -x ; echo ${DOCKER_USERNAME}

使用上述 Dockerfile 会发现无法输出 ${DOCKER_USERNAME} 变量的值,要想正常输出,你必须在 FROM 之后再次指定 ARG:

# 只在 FROM 中生效
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
# 要想在 FROM 之后使用,必须再次指定
ARG DOCKER_USERNAME=library
RUN set -x ; echo ${DOCKER_USERNAME}

8.VOLUME 定义匿名卷

格式为:

  • VOLUME [“<路径1>”, “<路径2>”…]
  • VOLUME <路径>

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中

为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据

VOLUME /data

在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置


9.EXPOSE 暴露端口

格式为 EXPOSE <端口1> [<端口2>...]

EXPOSE 指令是声明容器运行时提供服务的端口,这只是一个声明,在容器运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口

要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来

-p,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射


10.WORKDIR 指定工作目录

格式为 WORKDIR <工作目录路径>

使用 WORKDIR 指令可以来指定工作目录,以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录

如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令,例如:

WORKDIR /app
RUN echo "hello" > world.txt

如果你的 WORKDIR 指令使用的相对路径,那么所切换的路径与之前的 WORKDIR 有关:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

RUN pwd 的工作目录为 /a/b/c


11.USER 指定当前用户

格式:USER <用户名>[:<用户组>]

WORKDIR 是改变工作目录,USER 则是改变之后层的执行 RUN, CMD 以及 ENTRYPOINT 这类命令的身份

USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换

例如:

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

另外,如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu:

# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.12/gosu-amd64" \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]

12.LABEL 为镜像添加元数据

LABEL 指令用来给镜像以键值对的形式添加一些元数据

语法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

我们还可以用一些标签来申明镜像的作者、文档地址等:

LABEL org.opencontainers.image.authors="dahezhiquan"
LABEL org.opencontainers.image.documentation="https://dahezhiquan.gitbooks.io"

13.SHELL 指令

SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 ["/bin/sh", "-c"]

SHELL ["/bin/sh", "-c"]

RUN lll ; ls

SHELL ["/bin/sh", "-cex"]

RUN lll ; ls

两个 RUN 运行同一命令,第二个 RUN 运行的命令会打印出每条命令并当遇到错误时退出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/366598.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Django】如何设置支持多语种网站,中文/英文网站

首先&#xff0c;需要明确一点&#xff1a;我们要实现的中英对照翻译&#xff0c;这个翻译不是浏览器翻译的&#xff0c;也不是Django帮你翻译。这个需要你自己事先手动翻译好&#xff0c;存放在专门翻译文件中&#xff0c;Django只是事后调用而已。 第一步 新建项目后&#x…

Python||五城P.M.2.5数据分析与可视化_使用华夫图分析各个城市的情况(中)

目录 1.上海市的空气质量 2.成都市的空气质量 【沈阳市空气质量情况详见下期】 五城P.M.2.5数据分析与可视化——北京市、上海市、广州市、沈阳市、成都市&#xff0c;使用华夫图和柱状图分析各个城市的情况 1.上海市的空气质量 import numpy as np import pandas as pd impor…

【毕业日记】2024.01 - 慢下来,静待花开

转眼距离930离开鹅厂已经120天了&#xff0c;我是很能拖延的&#xff0c;或者是很懂自我麻痹的&#xff0c;这三个多月&#xff0c;一直想要写点东西纪念&#xff0c;一直拖一直拖一直拖…… 疫情这几年经济下行里裁员是个茶余饭后“嬉笑”之余经常被提起的词&#xff0c;部门滚…

JVM 笔记

JVM HotSpot Java二进制字节码的运行环境 好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;具有垃圾回收功能数组下标越界检查多态&#xff08;虚方法表&#xff09; JVM组成 类加载子系统&#xff08;Java代码转换为字节码&#xff09;运行时数据…

【代码随想录-链表】环形链表

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

GEDepth:Ground Embedding for Monocular Depth Estimation

参考代码&#xff1a;gedepth 出发点与动机 相机的外参告诉了相机在世界坐标系下的位置信息&#xff0c;那么可以用这个外参构建一个地面基础深度作为先验&#xff0c;后续只需要在这个地面基础深度先验基础上添加offset就可以得到结果深度&#xff0c;这样可以极大简化深度估…

【前端web入门第三天】02 CSS字体和文本

文章目录: 1.字体 1.1 字体大小 1.2 字体粗细 1.3 字体样式 1.4 行高 1.5 字体族 1.6 font 复合属性 2. 文本 2.1 文本缩进2.2 文本对齐方式2.3 文本修饰线2.4 color文字颜色 1.字体 1.1 字体大小 属性名: font-size属性值:文字尺寸&#xff0c;PC端网页最常用的单位px …

8. Threejs案例-SVG渲染器和WEBGL渲染器对比

8. Threejs案例-SVG渲染器和WEBGL渲染器对比 实现效果 知识点 SVG渲染器 (SVGRenderer) SVGRenderer 被用于使用 SVG 来渲染几何数据&#xff0c;所产生的矢量图形在以下几个方面十分有用&#xff1a; 动画标志 logo 或者图标 icon可交互的 2D 或 3D 图表或图形交互式地图复…

6、应急响应-日志自动提取自动分析ELKLogkitLogonTracerAnolog等

用途&#xff1a;个人学习笔记&#xff0c;欢迎指正 目录 背景: 一、日志自动提取-七牛Logki&观星应急工具 1、七牛Logkit: (支持Windows&Linux&Mac等) 2、观星应急工具(只支持Windows) 二、日志自动分析-Web-360星图&Goaccess&ALB&Anolog 1、W…

Pandas.Series.var() 方差 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.2.0 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 传送门&#xff1a; Pandas API参考目录 传送门&#xff1a; Pandas 版本更新及新特性 传送门&…

vit细粒度图像分类(六)FBSD学习笔记

1.摘要 从判别局部区域学习特征表示在细粒度视觉分类中起着关键作用。利用注意机制提取零件特征已成为一种趋势。然而&#xff0c;这些方法有两个主要的局限性:第一&#xff0c;它们往往只关注最突出的部分&#xff0c;而忽略了其他不明显但可区分的部分。其次&#xff0c;他们…

从零搭建Vue3 + Typescript + Pinia + Vite + Tailwind CSS + Element Plus开发脚手架

项目代码以上传至码云&#xff0c;项目地址&#xff1a;https://gitee.com/breezefaith/vue-ts-scaffold 文章目录 前言脚手架技术栈简介vue3TypeScriptPiniaTailwind CSSElement Plusvite 详细步骤Node.js安装创建以 typescript 开发的vue3工程集成Pinia安装pinia修改main.ts创…

图解Vue组件通讯【一图胜千言】

Vue的每个组件都有独自的作用域&#xff0c;组件间的数据是无法共享的&#xff0c;但实际开发工作中我们常常需要让组件之间共享数据&#xff0c;今天我们来学习下面三种组件通信方式&#xff1a; 父子组件之间的通信 兄弟组件之间的通信 祖先与后代组件之间的通信 1. 父子组件…

MySQL进阶之锁(全局锁以及备份报错解决)

锁 全局锁 全局锁就是对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状态&#xff0c;后续的DML的写语句&#xff0c;DDL语 句&#xff0c;已经更新操作的事务提交语句都将被阻塞。 其典型的使用场景是做全库的逻辑备份&#xff0c;对所有的表进行锁定&#xff…

Windows篇|连接共享文件夹映射驱动器教程

前言 昨天给小伙伴们分享了如何设置Windows共享文件夹的教程 超简单设置Windows共享文件夹,传输文件无烦恼 A电脑设置完共享文件夹之后,只要在同一局域网下,所有的电子设备都可以连接访问A电脑的共享文件夹里的内容。 这样就省去了U盘传输的麻烦,只要A电脑开着机,文件放入…

Mac如何设置一位数密码?

一、问题 Mac如何设置一位数密码&#xff1f; 二、解答 1、打开终端 2、清除全局账户策略 sudo pwpolicy -clearaccountpolicies 输入开机密码&#xff0c;这里是看不见的&#xff0c;输入完回车即可 3、重新设置密码 &#xff08;1&#xff09;打开设置-->用户和群组…

Docker 容器卷

1、概念介绍 如果是CentOS7安全模块会比之前系统版本加强&#xff0c;不安全的会先禁止&#xff0c;所以目录挂载的情况被默认为不安全的行为&#xff0c;在SELinux里面挂载目录被禁止掉了&#xff0c;如果要开启&#xff0c;我们一般使用--privlegedtrue命令&#xff0c;扩大…

Visual Studio Code安装配置C/C++教程 (windows版,亲测可行)

一.下载 Visual Studio Code https://code.visualstudio.com/ 二.安装 选择想要安装的位置: 后面的点击下一步即可。 三.下载编译器MinGW vscode只是写代码的工具&#xff0c;使用编译器才能编译写的C/C程序&#xff0c;将它转为可执行文件。 MinGW下载链接&#xff1a;…

24.云原生ArgoCD高级之数据加密seale sealed

云原生专栏大纲 文章目录 数据加密之seale sealedBitnami Sealed Secrets介绍Bitnami Sealed Secrets工作流程安装sealed-secrets和kubeseal安装sealed-secrets-controller安装kubeseal通过kubeseal将sealed-secrets公钥拿出来通过kubeseal加密secrets替换kustomize下secret为…

html2canvas 截图功能使用 VUE

html2canvas 是一个 JavaScript 库&#xff0c;可以将网页内容转换为 Canvas 元素&#xff0c;并生成图像或 PDF 文件。使用 html2canvas&#xff0c;你可以在客户端将网页的内容截图&#xff0c;并将其作为图像或 PDF 文件保存或分享。 以下是一些 html2canvas 库的特点和用途…
最新文章