dockerfile指令:


  • FROM:构建的新镜像是基于哪个镜像,例如:FROM centos:6

            语法:

            FROM <image>
            FROM <image>:<tag>

            FROM <image>:<digest> 

            三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest

  • MAINTAINER:镜像维护者姓名或邮箱地址,例如:MAINTAINER zhangsan@163.com

            语法:

            MAINTAINER <name>

  • RUN:构建镜像时运行的Shell命令,例如:RUN ["yum", "install", "httpd"] 或 RUN yum install httpd

            RUN命令有两种格式

                    1. RUN <command>
                    2. RUN ["executable", "param1", "param2"]

            第一种后边直接跟shell命令,在linux操作系统上默认 /bin/sh -c,在windows操作系统上默认 cmd /S /C

            第二种是类似于函数调用。可将executable理解成为可执行文件,后面就是两个参数。

            两种写法比对:

                    RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
                    RUN ["/bin/bash", "-c", "echo hello"]

            注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层。多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。RUN书写时的换行符是\。

  • CMD:运行容器时执行的Shell命令,

            语法有三种写法

  1.             CMD ["executable","param1","param2"]
                CMD ["param1","param2"]
                CMD command param1 param2

            第三种比较好理解了,就时shell这种执行方式和写法。第一种和第二种其实都是可执行文件加上参数的形式。

            例如:

         CMD ["-c", "/start.sh"]

         CMD ["/usr/sbin/sshd", "-D"]

         CMD /usr/sbin/sshd -D

  • EXPOSE:声明容器运行的服务端口,例如:EXPOSE 80 443


            功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口。如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上-P参数。

  • ENV:设置容器内环境变量,例如:ENV MYSQL_ROOT_PASSWORD 123456

            功能为设置环境变量,语法有两种:

                 ENV <key> <value>
                 ENV <key>=<value> ...

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

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

    用法:ADD <src>...<dest>

      ADD ["<src>",..."<dest>"]

            说明:<dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径

                      <src>可以是一个本地文件或者是一个本地压缩文件,还可以是一个url

                       如果把<src>写成一个url,那么ADD就类似于wget命令

                       注意:尽量不要把<scr>写成一个文件夹,如果<src>是一个文件夹了,复制整个目录的内容,包括文件系统元数据

    例如:

           ADD https://xxx.com/html.tar.gz /var/www/html

           ADD html.tar.gz /var/www/html

  • COPY:拷贝文件或目录到镜像,例如:COPY ./start.sh /start.sh

            语法如下:

                    COPY <src>... <dest>
                    COPY ["<src>",... "<dest>"]

            与ADD的区别:

                    COPY的<src>只能是本地文件,其他用法一致

  • ENTRYPOINT:运行容器时执行的Shell命令

            语法如下:

                    ENTRYPOINT ["executable", "param1", "param2"]

                    ENTRYPOINT command param1 param2

                    差别:第一种就是可执行文件加参数,第二种就是写shell

            例如:ENTRYPOINT ["/bin/bash", "-c", "/start.sh"]

      ENTRYPOINT /bin/bash -c '/start.sh'

            与CMD比较说明(这俩命令太像了,而且还可以配合使用):

                    1. 相同点:

                            只能写一条,如果写了多条,那么只有最后一条生效

                            容器启动时才运行,运行时机相同

                    2. 不同点:

                            ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖

                            如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数

  • VOLUME:指定容器挂载点到宿主机自动生成的目录或其他容器,例如:VOLUME ["/var/lib/mysql"]

            语法为:

                    VOLUME ["/data"]

            说明:

                    ["/data"]可以是一个JsonArray ,也可以是多个值。

                    所以如下几种写法都是正确的:

                            VOLUME ["/var/log/"]

                            VOLUME /var/log
                            VOLUME /var/log /var/db

            使用场景:一般的使用场景为需要持久化存储数据时,容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,所以当数据需要持久化时用这个命令。

  • USER:为RUN、CMD和ENTRYPOINT执行命令指定运行用户USER <user>[:<group>]或USER <UID>[:<GID>],例如:USER zhangsan

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

  • WORKDIR:为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录,例如:WORKDIR /data

            语法:

                    WORKDIR /path/to/workdir

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

            例如:

                    WORKDIR /a
                    WORKDIR b
                    WORKDIR c
                    RUN pwd

                    pwd执行的结果是/a/b/c

  • HEALTHCHECK:健康检查

            语法有两种:

                1. HEALTHCHECK [OPTIONS] CMD command
                2. HEALTHCHECK NONE

            说明:第一个的功能是在容器内部运行一个命令来检查容器的健康状况

                      第二个的功能是在基础镜像中取消健康检查命令

             [OPTIONS]的选项支持以下三中选项:

                    --interval=DURATION 两次检查默认的时间间隔为30秒

                    --timeout=DURATION 健康检查命令运行超时时长,默认30秒

                    --retries=N 当连续失败指定次数后,则容器被认为是不健康的,状态为unhealthy,默认次数是3

             注意:HEALTHCHECK命令只能出现一次,如果出现了多次,只有最后一个生效。

            CMD后边的命令的返回值决定了本次健康检查是否成功,具体的返回值如下:

                    0: success - 表示容器是健康的

                    1: unhealthy - 表示容器已经不能工作了

                    2: reserved - 保留值

            例如:

                    HEALTHCHECK --interval=5m --timeout=3s --retries=3 CMD curl -f http://localhost/ || exit 1

                    健康检查的命令是curl -f http://localhost/ ,两次健康检查的间隔时间是5m,命令超时时间为3s。

  • ARG:在构建镜像时指定一些参数

            语法:

                    ARG <name>[=<default value>]

            设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数

            如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning,提示如下:

                    [Warning] One or more build-args [foo] were not consumed.

    例如:

    FROM centos:6

    ARG user   # 定义一个参数,不在dockerfile中赋值

    USER $user

    # docker build --build-arg user=root Dockerfile .

  • LABEL:为镜像指定标签

             语法:

                    LABEL <key>=<value> <key>=<value> <key>=<value> ...

             一个Dockerfile种可以有多个LABEL,如下:

                    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会继承基础镜像种的LABEL,如遇到key相同,则值覆盖

  • STOPSIGNAL:当容器推出时给系统发送什么样的指令

            语法:

                    STOPSIGNAL signal


使用dockerfile构建带ssh服务的centos容器:

# 创建dockerfile

[root@centos7 ~]# mkdir dockerfile/centos_ssh -p 
[root@centos7 ~]# cd dockerfile/centos_ssh/
[root@centos7 centos_ssh]# vi dockerfile 
[root@centos7 centos_ssh]# cat dockerfile 
FROM centos
MAINTAINER "jerry12356@126.com"
ENV ROOT_PASSWORD 123456
RUN yum -y install openssh-server && yum clean all && \
  ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && \
  ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key && \
  /bin/echo $ROOT_PASSWORD |passwd --stdin root
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

# 使用dockerfile创建镜像

[root@centos7 centos_ssh]# docker build -t centos_ssh:v1 .
Sending build context to Docker daemon 2.048 kB
Step 1/6 : FROM centos
 ---> 1e1148e4cc2c
Step 2/6 : MAINTAINER "jerry12356@126.com"
 ---> Running in 8cad47a9e80a
 ---> ace0609297a5
Removing intermediate container 8cad47a9e80a
Step 3/6 : ENV ROOT_PASSWORD 123456
 ---> Running in a7ec1235fddb
 ---> 49d86fd09a96
Removing intermediate container a7ec1235fddb
Step 4/6 : RUN yum -y install openssh-server && yum clean all &&     ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key &&     ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key &&     /bin/echo $ROOT_PASSWORD |passwd --stdin root
 ---> Running in e9eb19cd496f
......
 ---> c366592c89f8
Removing intermediate container e9eb19cd496f
Step 5/6 : EXPOSE 22
 ---> Running in 5c0e295c1ed7
 ---> 7717f93524ae
Removing intermediate container 5c0e295c1ed7
Step 6/6 : CMD /usr/sbin/sshd -D
 ---> Running in f8b4fe42d264
 ---> e63f4d45cd57
Removing intermediate container f8b4fe42d264
Successfully built e63f4d45cd57

# 查看构建好的镜像

[root@centos7 centos_ssh]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos_ssh          v1                  e63f4d45cd57        2 hours ago         228 MB
docker.io/nginx     latest              f09fe80eb0e7        3 weeks ago         109 MB
docker.io/busybox   latest              3a093384ac30        2 months ago        1.2 MB
docker.io/centos    latest              1e1148e4cc2c        2 months ago        202 MB

# 使用构建完毕的镜像创建容器

[root@centos7 centos_ssh]# docker run -itd --name centos_ssh_01 -p 2222:22 centos_ssh:v1
ac59ac35955142095a1b59520f134a3de71a9a3f0d0305350d64adc91f886637
[root@centos7 centos_ssh]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND               CREATED             STATUS              PORTS                  NAMES
ac59ac359551        centos_ssh:v1       "/usr/sbin/sshd -D"   2 hours ago         Up 2 hours          0.0.0.0:2222->22/tcp   centos_ssh_01

# 尝试使用ssh直接连接docker容器

Docker系列(七):Dockerfile构建镜像_镜像


构建nginx容器:

[root@centos7 nginx]# ll
total 8
-rw-r--r-- 1 root root 1596 Mar  6 09:30 Dockerfile
-rw-r--r-- 1 root root 1924 Mar  3 14:03 nginx.conf
[root@centos7 nginx]# cat Dockerfile 
FROM centos:latest
MAINTAINER "jerry12356@126.com"
ENV NGINX_DIR="/usr/local/nginx" NGINX_VERSION=1.12.2 TIME_ZONE="Asia/Shanghai"
ADD http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz /tmp
RUN yum -y install gcc gcc-c++ libjpeg libjpeg-devel libpng libpng-devel \ 
    freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc \
    glibc-devel glib2 glib-devel bzip2 bzip2-devel curl curl-devel libidn \
    libidn-devel openssl openssl-devel make cmake pcre-devel && \
    useradd -u 602 nginx -M -s /sbin/nologin && \
    mkdir -p ${NGINX_DIR}/tmp/{client,proxy,fcgi} && \
    cd /tmp && \
    tar -zxf nginx-${NGINX_VERSION}.tar.gz && \
    cd nginx-${NGINX_VERSION} && \
    ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_gzip_static_module --http-client-body-temp-path=/usr/local/nginx/tmp/client/ --http-proxy-temp-path=/usr/local/nginx/tmp/proxy/ --http-fastcgi-temp-path=/usr/local/nginx/tmp/fcgi/ --with-poll_module --with-file-aio --with-http_realip_module --with-http_addition_module --with-http_random_index_module --with-pcre --with-http_stub_status_module --http-uwsgi-temp-path=/usr/local/nginx/uwsgi_temp --http-scgi-temp-path=/usr/local/nginx/scgi_temp && \
    make && \
    make install && \
    chown -R nginx:nginx $NGINX_DIR && \
    rm -rf /tmp/nginx* && \
    yum clean all && \
    echo "${TIME_ZONE}" > /etc/timezone && \ 
    ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime
COPY nginx.conf ${NGINX_DIR}/conf/
WORKDIR $NGINX_DIR
ENTRYPOINT ["./sbin/nginx", "-g", "daemon off;"]
EXPOSE 80


构建java容器:

[root@centos7 java]# ll
total 194820
-rw-r--r-- 1 root root   9672042 Feb  5 20:21 apache-tomcat-8.5.38.tar.gz
-rw-r--r-- 1 root root       522 Mar  5 13:55 Dockerfile
-rw-r--r-- 1 root root 189815615 Mar  2  2018 jdk-8u162-linux-x64.tar.gz
[root@centos7 java]# cat Dockerfile 
FROM centos:latest
MAINTAINER "jerry12356@126.com"
ENV JAVA_HOME /usr/local/jdk
COPY jdk-8u162-linux-x64.tar.gz /usr/local
COPY apache-tomcat-8.5.38.tar.gz /usr/local
RUN cd /usr/local && tar -zxf jdk-8u162-linux-x64.tar.gz && mv jdk1.8.0_162 jdk && \
    cd /usr/local && tar -zxf apache-tomcat-8.5.38.tar.gz && \
    mv apache-tomcat-8.5.38 tomcat && rm -f /usr/local/jdk-8u162-linux-x64.tar.gz && \
    rm -f /usr/local/apache-tomcat-8.5.38.tar.gz
WORKDIR /usr/local/tomcat
CMD ["bin/catalina.sh", "run"]
EXPOSE 8080

使用dockerfile构建后的镜像:

[root@centos7 java]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myjava              v1                  b0d98340393f        19 hours ago        800 MB
centos_ssh          v1                  d8b7ce88a878        44 hours ago        228 MB
mynginx             v1                  5cd531df9a2d        2 days ago          361 MB
docker.io/nginx     latest              f09fe80eb0e7        3 weeks ago         109 MB
docker.io/busybox   latest              3a093384ac30        2 months ago        1.2 MB
docker.io/centos    latest              1e1148e4cc2c        3 months ago        202 MB

nginx代理java服务实例:

1)准备java服务的nginx配置文件

[root@centos7 ~]# ll
total 12
-rw-------. 1 root root 1730 Oct 13  2017 anaconda-ks.cfg
drwxr-xr-x  7 root root 4096 Mar  5 13:30 dockerfile
drwxr-xr-x  3 root root 4096 Mar  6 09:44 testfiles
[root@centos7 ~]# cat testfiles/nginxconf/tomcat.conf 
server {
    listen  80;
    server_name localhost;
    location / {
        proxy_pass http://myjava01:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-Ip $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

2)分别启动nginx和java容器,为了使两者网络互联,这里使用过了--link的方式,当然也可以创建一个自定义网络,将两者都放到自定义网络中去

[root@centos7 ~]# docker run -itd --name myjava01 myjava:v1
c83ada9d3a8de902df7e95c57d77304b03354b5d9bdfbb3bf79d805033333c46
[root@centos7 ~]# docker run -itd --name mynginx01 -p 81:80 -v /root/testfiles/nginxconf:/usr/local/nginx/conf.d --link=myjava01 mynginx:v1
287b5a5fdb11d813c8940d6900786c3302ead0fa480e7369e3d3abe90a919538
[root@centos7 ~]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                NAMES
287b5a5fdb11        mynginx:v1          "./sbin/nginx -g '..."   4 seconds ago        Up 3 seconds        0.0.0.0:81->80/tcp   mynginx01
c83ada9d3a8d        myjava:v1           "bin/catalina.sh run"    About a minute ago   Up About a minute   8080/tcp             myjava01

3)尝试访问nginx,查看输出结果

[root@centos7 ~]# curl -I http://localhost:81
HTTP/1.1 200 
Server: nginx/1.12.2
Date: Thu, 07 Mar 2019 01:14:03 GMT
Content-Type: text/html;charset=UTF-8
Connection: close
Vary: Accept-Encoding
[root@centos7 ~]# curl http://localhost:81
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/8.5.38</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <link href="tomcat.css" rel="stylesheet" type="text/css" />
    </head>
........

4)进入容器中,查看nginx日志

[root@centos7 ~]# docker exec -it mynginx01 /bin/bash
[root@287b5a5fdb11 conf.d]# ll
total 4
-rw-r--r-- 1 root root 260 Mar  6 13:33 tomcat.conf
[root@287b5a5fdb11 conf.d]# cd ../logs/
[root@287b5a5fdb11 logs]# cat access.log 
172.17.0.1 - - [07/Mar/2019:09:14:03 +0800] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0"
172.17.0.1 - - [07/Mar/2019:09:17:55 +0800] "GET / HTTP/1.1" 200 11279 "-" "curl/7.29.0"

总结:已经成功的将java服务通过nginx代理,java容器无需映射外部端口,通过nginx映射的对应端口进行访问。另外,nginx容器编译时已经在nginx.conf中配置了 “include /usr/local/nginx/conf.d/*.conf;”,所以只需在本地新增nginx的配置文件,然后挂载到nginx容器即可。