从docker 官方下载的基础镜像有时候无法满足我们自己本身的业务需求,特别是配置文件,环境变量。这个时候通常需要自制我们自己的镜像。
DockerFile
Dokerfile是用来制作docker镜像的一个文本文件,并包含了构建镜像所需要的的指令及其参数。dockerfile 第一个非注释行必须是from,必须指明基础镜像。
Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
语法格式
两类:
- 指令
- 指令参数
注意点:
- 必须要有专用的工作目录
- 首字母必须大写
- 引用目录必须是在当前工作目录之下
参考样例:
1 | #基于centos镜像 |
制作镜像
1 | docker build -t smhttpd:1.0.0 . |
制作过程:
1 | luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker build -t smnginx . |
检查文件是否存在(不运行容器)
1 | luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker images |
rm选项运行后会自动删除容器,后面可以指定自定义命令,一般用于测试
1 | luodiPro:~/dockerfile_build/nginx$ docker run --name smweb1 --rm smnginx ls -a /var/www/html/ - |
指令介绍
FROM
FROM是最重要的一个且必须是DockerFile文件中的第一个非注释行,用于指定基准镜像。
语法:
1 | FROM <repository>[:<tag>] |
MAINTAINER(废弃)
指定镜像的制作者,一般是名称加联系方式。不过目前已经被LABLE替代
LABEL
LABEL 指令会添加元数据到镜像。LABEL是以键值对形式出现的。MAINTAINER可以是一个KEY,同时还可以指定多个元数据信息。
语法:
1 | LABEL maintainer="luodi <923401910@qq.com>" |
但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号
如下:
1 | LABEL multi.label1="value1" \ |
说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖
COPY
用于从Docker主机复制文件到创建的镜像文件中
语法:
1 | COPY <src> <dest> |
注意:
- src 必须是build上下文件中的路径,不能是父目录中的文件
- 如果src是目录,其内部文件或子目录会被递归复制,但src本身不会
- 如果dest事先不存在,它将会被自动创建,这包括其父目录路径
- 如果指定了多个src,或者在src使用通配符,dest必须是个目录,且必须是/结尾
ADD
功能和copy相似,但是ADD支持URL路径和TAR文件。如果是一个本地tar.gz包,会被执行tar -x命令被自动展开。但是URL上的tar包不会
语法:
1 | ADD <src> <dest> |
下载并解压文件
1 | ADD http://nginx.org/download/nginx-1.19.2.tar.gz /usr/local/src/ #下载到src但是并不会解压 |
WORKDIR
设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。
语法:
1 | WORKDIR /path/to/workdir |
USER
设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的
1 | USER daemo |
注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行
VOLUME
可实现挂载功能,用于在镜像中创建一个挂载点目录,以挂载Docker Host上的卷和其他容器上的卷到容器中
语法为:
1 |
|
说明:
[“/data”]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的
1 | VOLUME ["/var/log/"] |
一般的使用场景为需要持久化存储数据时
容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。
所以当数据需要持久化时用这个命令。
EXPOSE
用于为容器打开要监听的端口以实现外部通信,相当于暴露端口,会添加一条NAT规则。
只是声明可以暴露的端口,但是不会真正暴露。如果要暴露端口需要启动容器时加上-P选项,会随机做端口映射,可以使用-p 指定映射关系
语法:
1 | EXPOSE <port> |
-P
1 | luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run -dit -P --rm --name webhttpd smhttpd |
指定端口
1 | luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run -dit -p 8044:80 --name webhttp2 smhttpd |
ENV
功能为设置环境变量,可被Dockerfile文件中位于其后的其他指令调用
语法有两种
1 | ENV <key> <value> |
两者的区别就是第一种是一次设置一个,第二种是一次设置多个
样例:
1 | ENV DOC_ROOT /var/www/html/ |
可以在docker run 的时候设定变量值
1 | docker run --name testweb -e WEB_HOST="172.103.2.2" |
RUN
构建镜像时运行指定的命令,可以运行多次,如果有关联关系建议使用&&关联
语法:
1 | RUN <cmd> |
样例:
1 | RUN yum -y update |
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.
多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。
RUN书写时的换行符是\
CMD
容器启动时要运行的命令
语法:
1 | CMD ["executable","param1","param2"] |
样例:
1 | #当启动容器时执行的脚本文件 |