Dockerfile


1. 概述


Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

Dockerfile 由一行行命令语句组成,并且支持以 # 开头的注释行。

Docker分为四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时默认要执行的指令

例:

#基于centos镜像
FROM centos

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

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

#开启80端口
EXPOSE 80

#复制网站首页文件至镜像中web站点下
ADD index.html /var/www/html/index.html

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

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

一开始必须指明所基于的镜像名称,接下来一般会说明维护者信息。
后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命令。每运行一条RUN指令,镜像添加新的一层,并提交。
最后是CMD指令来指定运行容器时的操作指令。


2. 常用指令


在这里插入图片描述

2.1 FROM

指明构建的新镜像是来自于哪个基础镜像

FROM centos:7

2.2 MAINTAINER

指明镜像维护者及其联系方式(一般是邮箱地址)

MAINTAINER <name email_address>

MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者

LABEL maintainer="email_address"

2.3 RUN

构建镜像时运行的Shell命令

RUN ["yum", "install", "httpd"]
RUN yum install httpd

2.4 CMD

CMD用于指定启动容器时默认要执行的命令,每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。

CMD支持三种格式:

  • CMD [“executable”,“param1”,“param2”]使用exec执行,推荐方式
  • CMD command param1 param2在/bin/sh中执行,提供给需要交互的应用
  • CMD [“param1”,“param2”]提供给ENTRYPOINT的默认参数
CMD ["-C", "/start.sh"] 
CMD ["/usr/sbin/sshd", "-D"] 
CMD /usr/sbin/sshd -D

2.5 EXPOSE

声明容器运行的服务端口

EXPOSE 80 443

2.6 ENV

指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持

ENV MYSQL_ROOT_PASSWORD 123456
ENV JAVA_HOME /usr/local/jdk1.8.0_45

2.7 ADD

拷贝文件或目录到镜像中,如果是URL或压缩包,会自动下载或自动解压

ADD <src>...<dest>
ADD html.tar.gz /var/www/html
ADD https://xxx.com/html.tar.gz /var/www/html

2.8 COPY

拷贝文件或目录到镜像中,用法同ADD,只是不支持自动下载和解压

COPY ./start.sh /start.sh

2.9 ENTRYPOINT

启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序

ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C '/start.sh'

2.10 VOLUME

指定容器挂载点到宿主机自动生成的目录或其他容器

VOLUME ["/var/lib/mysql"]

2.11 USER

为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户

USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER edisonzhou

要临时获取管理员权限可以使用gosu,而不推荐sudo。如果不指定,容器默认是root运行


2.12 WORKDIR

为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。

WORKDIR /data

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

最终路径为/a/b/c

2.13 ONBUILD

配置当所创建的镜像作为其他镜像的基础镜像时,所执行的操作指令。

简单来说,用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

ONBUILD <其它指令>

3. 创建镜像


编写完成Dockerfile后,可以通过docker build命令来创建镜像。

基本的格式为docker build [选项] 路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下所有内容发送给Docker服务端,由服务端来创建镜像。因此一般建议放置Dockerfile的目录为空目录。

另外,可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让Docker忽略路径下的目录和文件。

要指定镜像的标签信息,可以通过-t选项。

例如,指定Dockerfile所在路径为/tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令:

docker build -t build_repo/first_image /tmp/docker_builder/

4. 案例:构建nginx镜像


创建一个目录,在该目录里编写dockerfile

[root@node01 ~]# mkdir myweb && cd myweb

下载nginx源码包

[root@node01 myweb]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@node01 myweb]# ls
nginx-1.18.0.tar.gz

编写Dockerfile

[root@node01 myweb]# vim dockerfile
[root@node01 myweb]# cat dockerfile 
FROM centos:7

RUN yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++ && yum -y groups mark install 'Development Tools'
ADD nginx-1.18.0.tar.gz /usr/src/
RUN useradd -r -M -s /sbin/nologin nginx && \
    mkdir -p /var/log/nginx && \
    chown -R nginx.nginx /var/log/nginx && \
    cd /usr/src/nginx-1.18.0 && \
    ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-debug --with-http_ssl_module --with-http_realip_module --with-http_image_filter_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log && \
    make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install && \
    echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh && \
    source /etc/profile.d/nginx.sh && \
    nginx

EXPOSE 80

运行docker命令构建镜像

[root@node01 myweb]# docker build -t nginx:v0.1 .
...
Removing intermediate container 8a6ec7eb5d69
Successfully built 3a6897f4901c

启动自定义镜像

[root@node01 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
nginx               v0.1                3a6897f4901c        About a minute ago   428 MB
docker.io/centos    7                   7e6257c9f8d8        2 weeks ago          203 MB
docker.io/centos    latest              0d120b6ccaa8        2 weeks ago          215 MB

[root@node01 ~]# docker run -it -p 80:80 --name nginx nginx:v0.1
[root@a89f59c68531 /]# nginx   //启动nginx

另起一个终端查看状态
[root@node01 myweb]# ss -antl |grep 80
LISTEN     0      128       [::]:80                    [::]:*
[root@node01 myweb]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
a89f59c68531        nginx:v0.1          "/bin/bash"         6 minutes ago       Up 6 minutes        0.0.0.0:80->80/tcp   nginx

使用ip访问

在这里插入图片描述