一文玩转dockerfile( 三 )


错误做法:
ADD http://example.com/big.tar.xz /usr/src/things/RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/thingsRUN make -C /usr/src/things all复制代码正确的做法:
RUN mkdir -p /usr/src/things     && curl -SL http://example.com/big.tar.xz     | tar -xJC /usr/src/things     && make -C /usr/src/things all复制代码RUN指令在使用较长的RUN指令时可以使用反斜杠分隔多行 。大部分使用RUN指令的常见是运行apt-wget命令,在该场景下请注意以下几点 。

  1. 不要在一行中单独使用指令RUN apt-get update 。当软件源更新后,这样做会引起缓存问题,导致RUN apt-get install指令运行失败 。所以,RUN apt-get update和RUN apt-get install应该写在同一行 。比如 RUN apt-get update && apt-get install -y package-1 package-2 package-3
  2. 避免使用指令RUN apt-get upgrade 和 RUN apt-get dist-upgrade 。因为在一个无特权的容器中,一些必要的包会更新失败 。如果需要更新一个包(如package-1),直接使用命令RUN apt-get install -y package-1 。
CMD和ENTRYPOINT命令CMD和ENTRYPOINT命令指定是了容器运行的默认命令,推荐二者结合使用 。使用exec格式的ENTRYPOINT指令设置固定的默认命令和参数,然后使用CMD指令设置可变的参数 。
比如下面这个例子:
FROM busyboxWORKDIR /AppCOPY run.sh /appRUN chmod +x run.shENTRYPOINT ["/app/run.sh"]CMD ["param1"]复制代码run.sh内容如下:
#!/bin/shecho "$@"复制代码运行后输出结果为param1, Dockerfile中CMD和ENTRYPOINT的顺序不重要(CMD写在ENTRYPOINT前后都可以) 。
当在windows系统下build dockerfile你可能会遇到这个问题
standard_init_linux.go:207: exec user process caused "no such file or directory"复制代码这是因为sh文件的fileformat是dos,这里需要修改为unix,不需要下载额外的工具,一般我们机器上安装了git会自带git bash,进入git bash,使用vi 编辑,在命令行模式下修改(:set ff=unix) 。
不要再Dockerfile中做端口映射使用Dockerfile的EXPOSE指令,虽然可以将容器端口映射在主机端口上,但会破坏Docker的可移植性,且这样的镜像在一台主机上只能启动一个容器 。所以端口映射应在docker run命令中用-p 参数指定 。
# 不要再Dockerfile中做如下映射EXPOSE 80:8080# 仅暴露80端口,需要另做映射EXPOSE 80复制代码实践Dockerfile的写法JAVA 服务的DockerFileFROM openjdk:8-jre-alpineENV spring_profiles_active=devENV env_java_debug_enabled=falseEXPOSE 8080WORKDIR /appADD target/smcp-web.jar /app/target/smcp-web.jarADD run.sh /appENTRYPOINT ./run.sh复制代码可以看到基础镜像是openjdk,然后设置了两个环境变量,服务访问端口是9090(意味着springboot应用中指定了server.port=8080),设置了工作目录是/app 。通过ENTRYPOINT设定了启动镜像时要启动的命令(./run.sh) 。这个脚本中的内容如下:
#!/bin/sh# Set debug options if requiredif [ x"${env_java_debug_enabled}" != x ] && [ "${env_java_debug_enabled}" != "false" ]; then    java_debug_args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"fi# ex: env_jvm_flags="-Xmx1200m -XX:MaxRAM=1500m" for productionjava $java_debug_args $env_jvm_flags -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -jar target/smcp-web.jar复制代码如果我们要指定jvm的一些参数,可以通过在环境变量中设置env_jvm_flags来指定 。
Maven Dockerfilemaven的Dockerfile也写的很好,这里我发上来也给大家参考下
FROM openjdk:8-jdkARG MAVEN_VERSION=3.6.3ARG USER_HOME_DIR="/root"ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0ARG BASE_URL=https://Apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binariesRUN mkdir -p /usr/share/maven /usr/share/maven/ref   && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz   && echo "${SHA}  /tmp/apache-maven.tar.gz" | sha512sum -c -   && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1   && rm -f /tmp/apache-maven.tar.gz   && ln -s /usr/share/maven/bin/mvn /usr/bin/mvnENV MAVEN_HOME /usr/share/mavenENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"COPY mvn-entrypoint.sh /usr/local/bin/mvn-entrypoint.shCOPY settings-docker.xml /usr/share/maven/ref/ENTRYPOINT ["/usr/local/bin/mvn-entrypoint.sh"]CMD ["mvn"]复制代码


推荐阅读