Dockerfile 指令详解

参考:

COPY 复制文件 | Docker 从入门到实践https://vuepress.mirror.docker-practice.com/image/dockerfile/copy/

指令集合:

COPY 复制文件

复制代码
COPY [--chown=<user>:<group>] <源路径>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

ADD 更高级的复制文件

自动解压缩这个压缩文件到 <目标路径>

还可以加上 --chown=<user>:<group> 选项来改变文件的所属用户及所属组

CMD 容器启动命令

CMD 指令就是用于指定默认的容器主进程的启动命令的

复制代码
shell 格式:CMD <命令>
exec 格式:CMD ["可执行文件", "参数1", "参数2"...]
参数列表格式:CMD ["参数1", "参数2"...]

ENTRYPOINT 入口点

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。

当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

复制代码
<ENTRYPOINT> "<CMD>"

EXPOSE 声明端口

复制代码
EXPOSE <端口1> [<端口2>...]

练习:

以centos的镜像为基础镜像,在其中安装httpd,添加apache的用户和组(如果没有的话)

同时在dockerfile中暴露80端口,编写index.html和page1.html拷贝至容器网站根目录

安装后编写ep.sh作为entrypoint要执行的脚本:参照redis编写

如果第一个参数是apache,则将所有的httpd相关的文件属主修改为apache

可修改/etc/httpd目录和/var/www/html目录下的所有文件的属主为apache

如果第一个参数是httpd,则运行httpd -D FOREGROUND启动httpd服务,如果第一个参数不是httpd,则将参数作为命令执行

复制代码
[root@localhost 520]# cat Dockerfile 
FROM centos
RUN rm -rf /etc/yum.repos.d/* \
    && curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo \
    && yum -y install httpd \
    && yum clean all 
EXPOSE 80
COPY index.html page1.html /var/www/html/
COPY ep.sh /
RUN chmod +x /ep.sh
ENTRYPOINT ["/ep.sh"]
CMD ["httpd"]
[root@localhost 520]# cat ep.sh 
#!/bin/bash
if [ "$1" = "apache" ] || [ "$1" = "httpd" ]; then
	chown -R apache:apache /etc/httpd /var/www/html
	httpd -D FOREGROUND
fi
$@  
[root@localhost 520]# docker build -t centos_httpd:v1 .
[root@localhost 520]# docker run -d --name my-centos  centos_httpd:v1 httpd
[root@localhost 520]# curl 172.17.0.2
Hello!

ENV 设置环境变量

复制代码
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

设置环境变量而已,无论是后面的其它指令,如 RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。

ARG 构建参数

复制代码
ARG <参数名>[=<默认值>]

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

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

VOLUME 定义匿名卷

复制代码
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

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

复制代码
VOLUME /data

这里的 /data 目录就会在容器运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行容器时可以覆盖这个挂载设置。比如:

复制代码
$ docker run -d -v mydata:/data xxxx

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

WORKDIR 指定工作目录

复制代码
WORKDIR <工作目录路径>

USER 指定当前用户

复制代码
USER <用户名>[:<用户组>]

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

复制代码
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

HEALTHCHECK 健康检查

复制代码
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK 支持下列选项:

--interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
--timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。

HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy

SHELL 指令

复制代码
SHELL ["executable", "parameters"]

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

复制代码
SHELL ["/bin/sh", "-c"]

RUN lll ; ls

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

RUN lll ; ls

在容器中管理数据主要有两种方式:

数据卷(Volumes)

挂载主机目录 (Bind mounts)

数据卷

数据卷管理:数据持久化

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用

  • 数据卷 的修改会立马生效

  • 数据卷 的更新,不会影响镜像

  • 数据卷 默认会一直存在,即使容器被删除

创建一个数据卷

复制代码
$ docker volume create my-vol

查看所有的 数据卷

复制代码
$ docker volume ls

DRIVER              VOLUME NAME
local               my-vol

在主机里使用以下命令可以查看指定 数据卷 的信息

复制代码
$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

启动一个挂载数据卷的容器

在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷

下面创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /usr/share/nginx/html 目录。

复制代码
$ docker run -d -P \
    --name web \
    # -v my-vol:/usr/share/nginx/html \
    --mount source=my-vol,target=/usr/share/nginx/html \
    nginx:alpine

查看数据卷的具体信息

在主机里使用以下命令可以查看 web 容器的信息

复制代码
$ docker inspect web

数据卷 信息在 "Mounts" Key 下面

复制代码
"Mounts": [
    {
        "Type": "volume",
        "Name": "my-vol",
        "Source": "/var/lib/docker/volumes/my-vol/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

删除数据卷

复制代码
$ docker volume rm my-vol

数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

无主的数据卷可能会占据很多空间,要清理请使用以下命令

复制代码
$ docker volume prune
相关推荐
0白露10 分钟前
Apifox Helper 与 Swagger3 区别
开发语言
Tanecious.1 小时前
机器视觉--python基础语法
开发语言·python
叠叠乐1 小时前
rust Send Sync 以及对象安全和对象不安全
开发语言·安全·rust
战族狼魂2 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
Tttian6223 小时前
Python办公自动化(3)对Excel的操作
开发语言·python·excel
xyliiiiiL3 小时前
ZGC初步了解
java·jvm·算法
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch4 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
独好紫罗兰4 小时前
洛谷题单2-P5713 【深基3.例5】洛谷团队系统-python-流程图重构
开发语言·python·算法
天天向上杰5 小时前
面基JavaEE银行金融业务逻辑层处理金融数据类型BigDecimal
java·bigdecimal