普拉多VX

人生一路,不问来时,不知归期

0%

DockerFile 构建镜像(一)

从docker 官方下载的基础镜像有时候无法满足我们自己本身的业务需求,特别是配置文件,环境变量。这个时候通常需要自制我们自己的镜像。

DockerFile

Dokerfile是用来制作docker镜像的一个文本文件,并包含了构建镜像所需要的的指令及其参数。dockerfile 第一个非注释行必须是from,必须指明基础镜像。
Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

语法格式

两类:

  • 指令
  • 指令参数

注意点:

  • 必须要有专用的工作目录
  • 首字母必须大写
  • 引用目录必须是在当前工作目录之下

参考样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#基于centos镜像
FROM centos #可以跟版本,如果不加默认是latest。FROM centos:latest

#维护人的信息
MAINTAINER The CentOS Project <923401910@qq.com>

#安装httpd软件包
RUN yum -y update
RUN yum -y install httpd

#开启80端口
EXPOSE 80

#复制网站首页文件至镜像中web站点下 index.html 必须要在当前目录存在
COPY index.html /var/www/html/

COPY static /var/www/html/static/ # 一定要以斜线结尾 static不存在将会创建

#复制该脚本至镜像中,并修改其权限
ADD run.sh /run.sh
RUN chmod 775 /run.sh

#当启动容器时执行的脚本文件
CMD ["/run.sh"]

制作镜像

1
2
docker build  -t smhttpd:1.0.0 . 
docker build -t smhttpd . #默认是latest

制作过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker build -t smnginx .
Sending build context to Docker daemon 7.68kB
Step 1/10 : FROM centos
---> 0d120b6ccaa8
Step 2/10 : MAINTAINER The CentOS Project <923401910@qq.com>
---> Using cache
---> 73711e378096
Step 3/10 : RUN yum -y update
---> Using cache
---> 17e83a7625bc
Step 4/10 : RUN yum -y install
---> Using cache
---> d65bbe61e58a
Step 5/10 : EXPOSE 80
---> Using cache
---> 013883f8a333
Step 6/10 : COPY index.html /var/www/html/
---> Using cache
---> 98a2d57e8bf1
Step 7/10 : COPY static /var/www/html/static/
---> 6156265c2a76
Step 8/10 : ADD run.sh /run.sh
---> 4832b8d59439
Step 9/10 : RUN chmod 775 /run.sh
---> Running in a60d60aa3e19
Removing intermediate container a60d60aa3e19
---> a95e79794432
Step 10/10 : CMD ["/run.sh"]
---> Running in 5f71bc6a29b1
Removing intermediate container 5f71bc6a29b1
---> 97a35e3ef1b7
Successfully built 97a35e3ef1b7
Successfully tagged smnginx:latest

检查文件是否存在(不运行容器)

1
2
3
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
smnginx latest 97a35e3ef1b7 2 minutes ago 278MB

rm选项运行后会自动删除容器,后面可以指定自定义命令,一般用于测试

1
2
3
4
5
6
7
8
9
10
11
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run --name smweb1 --rm smnginx ls -a /var/www/html/
.
..
index.html
static
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run --name smweb1 --rm smnginx ls -a /var/www/html/static
.
..
css
img
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$

指令介绍

FROM

FROM是最重要的一个且必须是DockerFile文件中的第一个非注释行,用于指定基准镜像。

语法:

1
2
FROM   <repository>[:<tag>] 
FROM <repository>@<digest> #hash码

MAINTAINER(废弃)

指定镜像的制作者,一般是名称加联系方式。不过目前已经被LABLE替代

LABEL

LABEL 指令会添加元数据到镜像。LABEL是以键值对形式出现的。MAINTAINER可以是一个KEY,同时还可以指定多个元数据信息。

语法:

1
2
LABEL maintainer="luodi <923401910@qq.com>"
LABEL version="1.0"

但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号

如下:

1
2
3
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"

说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

COPY

用于从Docker主机复制文件到创建的镜像文件中

语法:

1
2
COPY  <src> <dest>
COPY ["<src>","dest"]

注意:

  • src 必须是build上下文件中的路径,不能是父目录中的文件
  • 如果src是目录,其内部文件或子目录会被递归复制,但src本身不会
  • 如果dest事先不存在,它将会被自动创建,这包括其父目录路径
  • 如果指定了多个src,或者在src使用通配符,dest必须是个目录,且必须是/结尾

ADD

功能和copy相似,但是ADD支持URL路径和TAR文件。如果是一个本地tar.gz包,会被执行tar -x命令被自动展开。但是URL上的tar包不会

语法:

1
2
ADD  <src> <dest>
ADD ["<src>","dest"]

下载并解压文件

1
2
ADD http://nginx.org/download/nginx-1.19.2.tar.gz  /usr/local/src/   #下载到src但是并不会解压
ADD nginx-1.19.2.tar.gz /usr/local/src/ #解压本地文件到/usr/local/src/下

WORKDIR

设置工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次。

语法:

1
WORKDIR /path/to/workdir

USER

设置启动容器的用户,可以是用户名或UID,所以,只有下面的两种写法是正确的

1
2
USER daemo
USER UID

注意:如果设置了容器以daemon用户去运行,那么RUN, CMD 和 ENTRYPOINT 都会以这个用户去运行

VOLUME

可实现挂载功能,用于在镜像中创建一个挂载点目录,以挂载Docker Host上的卷和其他容器上的卷到容器中

语法为:

1
2

VOLUME ["/data"]

说明:

[“/data”]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的

1
2
3
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db

一般的使用场景为需要持久化存储数据时

容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。

所以当数据需要持久化时用这个命令。

EXPOSE

用于为容器打开要监听的端口以实现外部通信,相当于暴露端口,会添加一条NAT规则。

只是声明可以暴露的端口,但是不会真正暴露。如果要暴露端口需要启动容器时加上-P选项,会随机做端口映射,可以使用-p 指定映射关系

语法:

1
2
EXPOSE <port>
EXPOSE <port>[/protocol] <port>

-P

1
2
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run -dit  -P --rm --name webhttpd smhttpd
1d12e3386299 smhttpd "/run.sh" 2 minutes ago Up 2 minutes 0.0.0.0:32771->80/tcp webhttpd

指定端口

1
2
3
4
5
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker run -dit -p 8044:80 --name webhttp2 smhttpd
luodi@roddydeMacBook-Pro:~/dockerfile_build/nginx$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
62fafeb4aaa4 smhttpd "/run.sh" 3 seconds ago Up 2 seconds 0.0.0.0:8044->80/tcp webhttp2
1d12e3386299 smhttpd "/run.sh" 2 minutes ago Up 2 minutes 0.0.0.0:32771->80/tcp webhttpd

ENV

功能为设置环境变量,可被Dockerfile文件中位于其后的其他指令调用

语法有两种

1
2
ENV <key> <value>
ENV <key>=<value> ...

两者的区别就是第一种是一次设置一个,第二种是一次设置多个

样例:

1
2
3
4
ENV DOC_ROOT /var/www/html/

#复制网站首页文件至镜像中web站点下 index.html 必须要在当前目录存在
COPY index.html $DOC_ROOT # ${DOC_ROOT:-/var/www/html/} 如果没有值,赋默认值

可以在docker run 的时候设定变量值

1
docker run --name testweb -e WEB_HOST="172.103.2.2"

RUN

构建镜像时运行指定的命令,可以运行多次,如果有关联关系建议使用&&关联

语法:

1
2
RUN <cmd>
RUN ["cmd","参数1","参数2"]

样例:

1
2
RUN yum -y update
RUN yum -y install httpd

注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.

多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。

RUN书写时的换行符是\

CMD

容器启动时要运行的命令

语法:

1
2
3
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

样例:

1
2
#当启动容器时执行的脚本文件
CMD ["/run.sh"]