参考:
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