Dockerfile 相关指令
dockerfile 文件中的常见指令:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
FROM:指定基础镜像
定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。FROM 就是指定基础镜像,此指令必需放在有效指令的第一行。怎么选择合适的镜像呢?对于不同的软件官方都提供了相关的docker镜像,比如:nginx、redis、mysql、httpd、tomcat等服务类的镜像,也有操作系统类,如:centos、ubuntu、debian等。建议使用官方镜像,比较安全。
格式:
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
说明:
--platform 指定镜像的平台,比如:linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest
范例:
FROM scratch #所有镜像的起源镜像,相当于Object类
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
LABEL:指定镜像元数据
可以指定镜像元数据,如:镜像作者等
LABEL <key>=<value> <key>=<value> <key>=<value> ...
范例:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates /
that label-values can span multiple lines."
范例:多标签写法
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" /
multi.label2="value2" /
other="value3"
docker inspect 命令可以查看LABEL
范例:
"Labels": {
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},
MAINTAINER: 指定维护者信息
此指令已过时,用LABEL代替
MAINTAINER <name>
范例:
MAINTAINER wangxiaochun <root@wangxiaochun.com>
#用LABEL代替
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
RUN:执行shell命令
RUN 指令是用来执行命令的。shell命令功能丰富,所以RUN 指令经常用来调用shell指令
注意:run可以写多个,每一个run指令都会建立一层,所以尽可能合并成一条指令
#shell 格式:
RUN <命令>
#exec 格式:
RUN ["可执行文件", "参数1", "参数2"]
范例:
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
RUN ["/bin/bash", "-c", "echo hello world"]
RUN yum -y install epel-release /
&& yum -y install nginx /
&& rm -rf /usr/share/nginx/html/*
&& echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html
COPY:复制文本
复制本地主机的
COPY <src>... <dest>
COPY ["<src1>",... "<目标路径>"]
说明:
-
可以是多个、以及使用通配符,通配符规则满足Go的filepath.Match 规则 -
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等 - 如果
是目录,只复制目录内容,而非目录本身
范例:
COPY hom* /mydir/ COPY hom?.txt /mydir/
ADD:复制和解包文件
该命令可认为是增强版的COPY,不仅支持COPY,还支持解缩。可以将复制指定的
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
说明:
- 如果src是目录,只复制目录中的内容,而非目录本身
- 如果src是本地打包或压缩文件,如gzip, bzip2 ,xz ,将解包
- 如果src是一个 URL ,下载后的文件权限自动设置为 600
范例:
ADD test relativeDir/ # adds "test" to WORKDIR
/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
CMD:容器启动命令
指定启动容器时默认执行的命令,即:如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么就会使用执行CMD指定的默认的命令
每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
如果用户启动容器时指定了运行的命令,如:docker run xxx /bin/bash,则/bin/bash 会覆盖 CMD 指定的命令
# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径
CMD ["executable","param1","param2"]
# 在 /bin/sh 中执行,提供给需要交互的应用;
CMD command param1 param2
# 提供给 ENTRYPOINT 的默认参数;
CMD ["param1","param2"]
范例:
CMD ["nginx", "-g", "daemon off;"]
范例:
FROM ubuntu:18.04
RUN apt update /
&& apt -y install curl /
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s","https://ip.cn"]
[root@centos8 ubuntu]#podman run 9b cat /etc/issue
Ubuntu 18.04.4 LTS /n /l
[root@centos8 ubuntu]#podman run 9b
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#cat /etc/etc/issue覆盖了curl命令
[root@centos8 ubuntu]#podman run 9b cat /etc/issue
Ubuntu 18.04.4 LTS /n /l
ENTRYPOINT:入口点
功能类似于CMD,配置容器启动后执行的命令及参数,并且不可被 docker run 提供的参数覆盖,而是追加
如果docker run命令有参数,那么参数全部都会作为ENTRYPOINT的参数。如果docker run后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),那么CMD的全部内容会作为ENTRYPOINT的参数
可以通过docker run –entrypoint 参数在运行时替换
使用CMD要在运行时重新写命令才能追加运行参数,ENTRYPOINT则可以运行时接受新参数
每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效
# 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"]
# shell中执行
ENTRYPOINT command param1 param2
范例:
FROM ubuntu:18.04
RUN apt update /
&& apt -y install curl /
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s","https://ip.cn"]
[root@centos8 ubuntu]#podman run -it --rm f68e006
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
#追加-i参数
[root@centos8 ubuntu]#podman run -it --rm f68e006 -i
HTTP/2 200
date: Sun, 23 Feb 2020 08:05:19 GMT
content-type: application/json; charset=UTF-8
set-cookie: __cfduid=d4a22496ea6f3b2861763354f8ca600711582445119; expires=Tue, 24-Mar-20 08:05:19 GMT; path=/; domain=.ip.cn; HttpOnly; SameSite=Lax
cf-cache-status: DYNAMIC
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
alt-svc: h3-25=":443"; ma=86400, h3-24=":443"; ma=86400, h3-23=":443"; ma=86400
server: cloudflare
cf-ray: 5697b1ac1862eb41-LAX
{"ip": "111.199.187.36", "country": "北京市", "city": "联通"}
ENV:设置环境变量
指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
范例:
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-PG_MAJOR/bin:$PATH
ARG:构建参数
指定变量
ARG <name>[=<default value>]
如果和ENV同名,ENV覆盖ARG变量
和ENV不同的是,容器运行时不会存在这些环境变量
可以用 docker build –build-arg <参数名>=<值> 来覆盖
范例:
FROM busybox
ARG user1=someuser
ARG buildno=1
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
VOLUME:挂载点
在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录/var/lib/containers/storage/volumes/<id>/_data
挂载至VOLUME 指令指定的容器目录。即使容器后期删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。
VOLUME ["<容器内路径1>", "<容器内路径2>"...]
VOLUME <路径>
范例:在容器创建一个/data/ 的挂载点
VOLUME [ "/data","/data2" ]
范例:
[root@centos8 ~]#cat /data/dockerfile/system/alpine/Dockerfile
FROM alpine:3.11
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY repositories /etc/apk/repositories
VOLUME [ "/testdata" , "/testdata2" ]
[root@centos8 alpine]#podman run -it --rm 8ef61dd3959da3f sh
/ # df
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 104806400 3656380 101150020 3% /
tmpfs 65536 0 65536 0% /dev
/dev/sda2 104806400 3656380 101150020 3% /testdata2
/dev/sda2 104806400 3656380 101150020 3% /testdata
/ # cp /etc/issue /testdata/f1.txt
/ # cp /etc/issue /testdata2/f2.txt
[root@centos8 ~]#tree /var/lib/containers/storage/volumes/
/var/lib/containers/storage/volumes/
├── 725f0f67921bdbffbe0aaf9b015d663a6e3ddd24674990d492025dfcf878529b
│ └── _data
│ └── f1.txt
└── fbd13e5253deb375e0dea917df832d2322e96b04ab43bae061584dcdbe7e89f2
└── _data
└── f2.txt
4 directories, 2 files
EXPOSE:暴露端口
告诉 Docker 服务端容器暴露的端口号,供互联系统使用。
EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射
因此,在启动容器时需要通过 -P 或-p ,Docker 主机会分配一个端口转发到指定暴露的端口,才可以使用
EXPOSE <端口1> [<端口2>...]
WORKDIR:指定工作目录
为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内的默认目录
WORKDIR /path/to/workdir
范例:
#两次run不在一个环境内,可以使用WORKDIR
RUN cd /app
RUN echo "hello" > world.txt
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为 /a/b/c
ONBUILD:子镜像引用父镜像的指令
可以用来配置当创建当前镜像的子镜像时,会自动触发执行的指令。
ONBUILD [INSTRUCTION]。
例如,Dockerfile 使用如下的内容创建了镜像 image-A。
...
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src...
如果基于 image-A 创建新的镜像时,新的Dockerfile中使用 FROM image-A指定基础镜像时,会自动执行ONBUILD 指令内容,等价于在后面添加了两条指令。
FROM image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
使用 ONBUILD
指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild
USER:指定当前用户
指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户
当服务不需要管理员权限时,可以通过该命令指定运行用户
这个用户必须是事先建立好的,否则无法切换
要临时获取管理员权限可以使用 gosu,而不推荐 sudo
USER <user>[:<group>]
USER <UID>[:<GID>]
范例:
RUN groupadd -r mysql && useradd -r -g mysql mysql
USER mysql
HEALTHCHECK:健康检查
检查容器的健康性
HEALTHCHECK [选项] CMD <命令> #设置检查容器健康状况的命令
HEALTHCHECK NONE #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 支持下列选项:
--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3次。
范例
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s /
CMD curl -fs http://localhost/ || exit 1
STOPSIGNAL:退出容器的信号
该STOPSIGNAL
指令设置将被发送到容器退出的系统调用信号。该信号可以是与内核syscall表中的位置匹配的有效无符号数字(例如9),也可以是SIGNAME格式的信号名称(例如SIGKILL)
STOPSIGNAL signal
.dockerignore文件
官方文档:https://docs.docker.com/engine/reference/builder/#dockerignore-file
与.gitignore文件类似,生成构建上下文时Docker客户端应忽略的文件和文件夹指定模式。
以下是完整的语法:
'*' 匹配任何非分隔符字符序列
'?' 匹配任何单个非分隔符
'['['^'] {character-range}']'
字符类(必须是非空的)
c匹配字符c (c!='*','?','//','[')
'//' 表示 /
'**' 匹配任意数量的目录(包括零)例如,**/*.go将排除.go 在所有目录中找到的以该结尾的所有文件,包括构建上下文的根。
'!' 表示取反,可用于排除例外情况
以此字符开头的'#'行将被忽略:将其用于注释
范例:
#排除 test 目录下的所有文件
test/*
#排除 md 目录下的 xttblog.md 文件
md/xttblog.md
#排除 xttblog 目录下的所有 .md 的文件
xttblog/*.md
#排除以 xttblog 为前缀的文件和文件夹
xttblog?
#排除所有目录下的 .sql 文件夹
**/*.sql
范例:
#除了README的md不排外,排除所有md文件,但不排除README-secret.md
*.md
!README*.md
README-secret.md
#除了所有README的md文件以外的md都排除
*.md
README-secret.md
!README*.md
Dockerfile文件指令总结
本文链接:http://www.yunweipai.com/34830.html
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/52661.html