• Dockerfile 入门实践


    Dockerfile 入门实践

    一些事项

    • 书写Dockerfile文件时,设定工作目录时,如果要忽略工作目录下的一些文件,可以使用 .dockerignore 文件
    • 变量设定默认值:${variable:-word},当 variable 不存在或者为空是,最后的值为 word
    • 还有另一种格式:${variable:+word},它表示当 variable 存在或者为真时,则返回 word

    指令

    FROM

    • FROM <registry>:<tag>

    COPY

    • COPY <src> <dest>
    • 其中src是上下文中的目录(工作目录或工作子目录);dest表示镜像中的目标路径
    • 目录自身不会复制过去,但其内容会全部复制过去(下方会做实践)
    • dest必须以 / 结尾,以表示目录
    • 先来个简单的Dockerfile:
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    
    • 此时进行构建:docker build -t testnginx:v0.1.0 .
    • 接着可以启动容器,并查看对应的目录 /mydata 下的文件 index.html 是否存在:docker run --name myinginx1 --rm testnginx:v0.1.0 cat /mydata/index.html
    • 接下来做个试验:将/etc/yum.repos.d目录下的文件复制到镜像中
    • 在之前的Dockerfile内容基础上继续写:
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    
    • 构建镜像:docker build -t testnginx:v0.1.2 .
    • 启动容器并查看:docker run --name myinginx1 --rm testnginx:v0.1.2 ls /mydata/yumRepos
    • 可以看到yum.repos.d目录本身并没有被拷贝进入 /mydata/yumRepos 中

    ADD

    • ADD <src> <dest>
    • 向目标镜像文件中打包文件,如果 src 是上下文目录下的文件,并且是tar.gz之类的压缩文件,会进行解压到目标路径下。
    • src 如果是网络地址,则只会下载该文件,而不会解压。
    • dest 代表目标路径,路径必须以 / 结尾

    ADD实践

    • 在Dockerfile中使用ADD:
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    ADD http://nginx.org/download/nginx-1.15.8.tar.gz /usr/local/nginx/
    
    • 构建:docker build -t testnginx:v0.1.3 .,不要忘记后边有个 .
    • 启动容器,验证容器中是否存在下载后的文件:docker run --name myinginx1 --rm testnginx:v0.1.3 ls /usr/local/nginx

    [root@localhost t0117]# docker run --name myinginx1 --rm testnginx:v0.1.3 ls /usr/local/nginx

    nginx-1.15.8.tar.gz

    WORKDIR

    • WORKDIR <dirpath>
    • 用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY、ADD等指令设定工作目录

    实践WORKDIR

    • 在Dockerfile中使用WORKDIR:
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    WORKDIR /usr/local/nginx
    ADD http://nginx.org/download/nginx-1.15.8.tar.gz ./src/
    
    • 在上面的指令中,在镜像里,先将工作目录切换到 /usr/local/nginx,然后下载 nginx-1.15.8.tar.gz 文件到基于工作目录/usr/local/nginx 下的 src 目录下
    • 构建镜像:docker build -t testnginx:v0.1.4 .
    • 启动容器,验证容器中是否存在下载后的文件:docker run --name myinginx1 --rm testnginx:v0.1.4 ls /usr/local/nginx/src

    VOLUME

    • VOLUME <mountPoint>
    • 挂载数据卷

    实践VOLUME

    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    WORKDIR /usr/local/nginx
    ADD http://nginx.org/download/nginx-1.15.8.tar.gz ./src/
    VOLUME /data/mysql
    
    • 构建镜像:docker build -t testnginx:v0.1.5 .
    • 启动容器,并查看挂载的情况:docker run --name myinginx1 --rm testnginx:v0.1.5 mount
    • 此时可以看到显示的结果中有一行如下:

    /dev/mapper/centos-root on /data/mysql type xfs (rw,relatime,attr2,inode64,noquota)

    • 也可以使用 docker inspect {container} 的方式,查看挂载卷情况:
    • 启动容器:docker run --name myinginx1 --rm testnginx:v0.1.5 sleep 60
    • 此时,新开一个shell窗口,用命令行查看:docker inspect testginx:v0.1.5
    • 或者进入容器内部查看:docker exec -it myinginx1 sh
    • 可以看到存在文件夹:/data/mysql

    EXPOSE

    • EXPOSE <port>[/protocol]
    • 其中protocol是指协议,值为:tcp或udp,默认为tcp
    • 也可暴露多个端口:EXPOSE 80/tcp 91/udp

    EXPOSE实践

    • 编写Dockerfile:
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    WORKDIR /usr/local/nginx
    ADD nginx-1.15.8.tar.gz ./src/
    VOLUME /data/mysql
    EXPOSE 80/tcp
    
    • 构建:docker build -t testnginx:v0.1.6.1
    • 运行:docker run --name myinginx1 -P --rm testnginx:v0.1.6.1 sleep 60
    • -P 的作用就是暴露镜像中设定好的对外端口,而不用则命令行中额外指定
    • 此时可以查看docker port myinginx1,显示的是容器的端口对应宿主机上的端口

    ENV

    • ENV <key> <value>
    • ENV <key>=<value>
    • 为镜像定义所需的环境变量
    • 第一种方式只能设置一个变量。第2中可以设置多个,如果value中包含空格,可以使用 \ 转义

    实践ENV

    • 编写Dockerfile
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    ENV PACKAGE_NAME=/nginx-1.15.8
    WORKDIR /usr/local/nginx
    ADD ${PACKAGE_NAME}.tar.gz ./src/
    VOLUME /data/mysql
    EXPOSE 80/tcp
    
    • 构建:docker build -t testnginx:v0.1.7 .
    • 启动:docker run --name myinginx1 -P --rm testnginx:v0.1.7 ls /usr/local/nginx/src/nginx-1.15.8
    • 此时之前的将nginx包放入镜像中的操作还是正常运行的。
    • 以上,是在build阶段,设定好环境变量,实际上在容器启动阶段,也可以进行设定环境变量,可以通过 docker run --help 查看命令,其中有一个 -e 参数,可以在run阶段设定环境变量

    CMD

    • CMD <command>
    • CMD ["<executable>","<param1>","<param2>"]
    • CMD ["<param1>","<param2>"]
    • Dockerfile中可以有多个CMD指令,但只有最后一个会生效
    • 第3种方式,没有命令只有参数,它的作用可以用于为 ENTRYPOINT 提供参数

    ENTRYPOINT

    • ENTRYPOINT [<"excutable","param1","param2">]
    • 启动容器时,可以使用自定义的命令覆盖镜像中默认的命令

    ENTRYPOINT实践

    • 编写Dockerfile
    FROM docker.io/nginx:1.15-alpine
    MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    ENV PACKAGE_NAME=nginx-1.15.8
    WORKDIR /usr/local/nginx
    #ADD ${PACKAGE_NAME}.tar.gz ./src/
    COPY ${PACKAGE_NAME}.tar.gz ./src/
    #ADD http://nginx.org/download/${PACKAGE_NAME}.tar.gz ./src/
    RUN mkdir -p /data/nginx && \
            tar xf ./src/${PACKAGE_NAME}.tar.gz -C /data/nginx
    ADD entrypoint.sh /bin/
    
    VOLUME /data/mysql
    EXPOSE 80/tcp
    CMD ["/usr/sbin/nginx","-g","daemon off;"]
    ENTRYPOINT ["/bin/entrypoint.sh"]
    
    • 其中entrypoint.sh的内容如下:
    #!/bin/sh
    #
    cat > /etc/nginx/conf.d/www.conf << EOF
    server{
            server_name $HOSTNAME;
            listen ${IP:-0.0.0.0}:${PORT:-80};
            root ${NGX_DOC_ROOT:-/usr/share/nginx/html};
    }
    EOF
    exec "$@";
    
    • 注意,在ENTRYPOINT的命令里,不可写成 ENTRYPOINT ["/bin/entrypoint.sh;"],也即是不能加上分号
    • 构建:docker build -t testnginx:v0.1.9.14 .
    • 启动容器查看:docker run --name myinginx1 -P --rm testnginx:v0.1.9.14 ls /bin

    USER

    • USER <uid>/<userName>
    • 运行容器时指定用户名或用户id

    HEALTHCHECK

    • HEALTHCHECK <option> <command>
    • 健康检查,检查容器的状态是否正常
    • 例如:HEALTHCHECK --start-period=3s CMD wget -0 - -q http://${IP:-0.0.0.0}:${PORT:-80}/

    ARG

    • ARG <name>[=<default value>]
    • 适用于build时
    • 在构建的命令中,可以使用 --build-arg <name>=<value> 进行设定

    ARG实践

    • 例如在编写Dockerfile时:
    FROM docker.io/nginx:1.15-alpine
    #MAINTAINER "SUHANYU <suhanyujie@qq.com>"
    ARG maintainer="SUHANYU <suhanyujie@qq.com>"
    LABEL "maintainer ${maintainer}"
    COPY index.html /mydata/
    COPY yum.repos.d /mydata/yumRepos/
    ENV PACKAGE_NAME=nginx-1.15.8
    WORKDIR /usr/local/nginx
    #ADD ${PACKAGE_NAME}.tar.gz ./src/
    COPY ${PACKAGE_NAME}.tar.gz ./src/
    #ADD http://nginx.org/download/${PACKAGE_NAME}.tar.gz ./src/
    RUN mkdir -p /data/nginx && \
            tar xf ./src/${PACKAGE_NAME}.tar.gz -C /data/nginx
    ADD entrypoint.sh /bin/
    
    VOLUME /data/mysql
    EXPOSE 80/tcp
    CMD ["/usr/sbin/nginx","-g","daemon off;"]
    ENTRYPOINT ["/bin/entrypoint.sh"]
    
    • 构建:docker build -t testnginx:v.0.1.10.1 .
    • 查看:docker image inspect testnginx:v0.1.10.1
    • 此时,可以看到其中的LABEL中有所设定的值
    • 重新构建,在构建的命令中设定arg:docker build --build-arg maintainer="<suhanyujie@qq.com>" -t testnginx:v0.1.10.2 .
    • 查看:docker image inspect testnginx:v0.1.10.2
    • 此时,可以在输出中看到,包含如下的LABEL内容:
    "Labels": {
                    "maintainer": "<suhanyujie@qq.com>"
                },
    

    ONBUILD

    • ONBUILD <instruction>
    • 在Dockerfile中定义一个触发器
    • 例如你已经构建了一个镜像 testnginx:v0.1.10.1,并且在你构建 testnginx:v0.1.10.1 时,你使用了 ONBUILD。在此基础上,如果构建一个新的镜像是,并且是 FROM testnginx:v0.1.10.1,此时构建这个新镜像时就会触发执行上一个镜像的 ONBUILD 所对应的指令。

    RUN

    RUN

    * RUN <command>
    * RUN ["<executable>","<param1>","<param2>"]
    * 第1中方式中,command通常是一个shell命令,以 `/bin/sh -c` 的方式运行
    
    • RUN <command>
    • RUN ["<executable>","<param1>","<param2>"]
    • 如果要运行的命令依赖于shell特性,可以使用如下的方式:

    RUN ["/bin/sh","-c","<executable>","<param1>"]

    其他

    • 运行在docker容器中的服务,一般是shell的子进程
    • 在linux系统中,后台运行的服务程序一般是init的子进程,也就是管理进程的子进程
  • 相关阅读:
    第5次系统综合实践
    第4次系统综合实践
    第3次系统综合实践
    第2次实践作业
    第1次实践作业
    第03组 Beta版本演示
    第03组 Beta冲刺(4/4)
    OO第四单元总结
    OO第三单元总结
    OO第二单元总结
  • 原文地址:https://www.cnblogs.com/wxwgk/p/11695949.html
Copyright © 2020-2023  润新知