Dockerfile总结:常用指令、注意事项、常见错误(no such file or directory、Permission denied)

什么是 Dockerfile?

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


指令详解

点击参考:使用 Dockerfile 定制镜像

注意事项

  • RUN (docker镜像越来越大的原因之一)

    RUN <命令行命令> # <命令行命令> 等同于,在终端操作的 shell 命令。

    注意: Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

    FROM centos
    RUN yum install wget
    RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
    RUN tar -xvf redis.tar.gz
    
    以上执行会创建 3 层镜像。可简化为以下格式:
    
    FROM centos
    RUN yum install wget \
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
        && tar -xvf redis.tar.gz
    

    如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

  • CMD

    作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

    注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

    格式:
    CMD <shell 命令>
    CMD ["<可执行文件或命令>","","",…]
    CMD ["","",…] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

    推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

  • ENTRYPOINT

    类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

    但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

    优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

    注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

    格式:

    ENTRYPOINT ["","","",…]

    可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。

    示例:

    假设已通过 Dockerfile 构建了 nginx:test 镜像:

    FROM nginx

    ENTRYPOINT [“nginx”, “-c”] # 定参
    CMD ["/etc/nginx/nginx.conf"] # 变参

    1、不传参运行

      docker run  nginx:test
    

    容器内会默认运行以下命令,启动主进程。

      nginx -c /etc/nginx/nginx.conf
    

    2、传参运行

      docker run  nginx:test -c /etc/nginx/new.conf
    

    容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

      nginx -c /etc/nginx/new.conf
    
  • FROM

    多个FROM声明
    尝试使用多个FROM声明来将不同的镜像组合到一起,这样不会起任何作用。Docker仅使用最后一个FROM并且忽略前面所有的。

    所以如果你有这样的Dockerfile:

    # !!! ANTIPATTERN !!!
    FROM node:6.2.1
    FROM python:3.5
    CMD ["sleep", "infinity"]
    # !!! ANTIPATTERN !!! 
    

    那么docker exec进入运行的容器中,会得到下面的结果:

    $ docker exec -it d86fcf0775d3 bash
    root@d86fcf0775d3:/# which python
    /usr/local/bin/python
    root@d86fcf0775d3:/# which node
    root@d86fcf0775d3:/#
    

    这其实是GitHub上的一个问题:合并不同的镜像,但它看起来不会很快就增加的功能。


dockerfile常见错误

  • COPY时提示no such file or directory

    例如如下错误信息:

      COPY failed: stat /var/lib/docker/..... no such file or directory
    

    可能的原因:

      文件不存在
      文件路径写法错误
    

    docker镜像打包的COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。
    实际操作中正确的方式和错误的方式参考如下:
    正确:

    COPY ./package.json /app/
    COPY package.json /usr/src/app/
    

    错误:

    COPY ../package.json /app
    或者
    COPY /opt/xxxx /app
    
  • Permission denied问题

    执行

      RUN chmod +x configure
    

    时报错

      chmod: cannot access 'configure': Permission denied
    

    提升权限即可,如数据/程序在‘/home/’

      RUN chmod 777 /home/
    

猜你喜欢

转载自blog.csdn.net/zengNLP/article/details/106309817