从特定步骤重建docker图像

sag*_*sag 43 docker dockerfile

我有下面的Dockerfile.

FROM ubuntu:14.04
MAINTAINER Samuel Alexander <samuel@alexander.com>

RUN apt-get -y install software-properties-common
RUN apt-get -y update

# Install Java.
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
RUN add-apt-repository -y ppa:webupd8team/java
RUN apt-get -y update
RUN apt-get install -y oracle-java8-installer
RUN rm -rf /var/lib/apt/lists/*
RUN rm -rf /var/cache/oracle-jdk8-installer

# Define working directory.
WORKDIR /work

# Define commonly used JAVA_HOME variable
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

# JAVA PATH
ENV PATH /usr/lib/jvm/java-8-oracle/bin:$PATH

# Install maven
RUN apt-get -y update
RUN apt-get -y install maven

# Install Open SSH and git
RUN apt-get -y install openssh-server
RUN apt-get -y install git

# clone Spark
RUN git clone https://github.com/apache/spark.git
WORKDIR /work/spark
RUN mvn -DskipTests clean package

# clone and build zeppelin fork
RUN git clone https://github.com/apache/incubator-zeppelin.git
WORKDIR /work/incubator-zeppelin
RUN mvn clean package -Pspark-1.6 -Phadoop-2.6 -DskipTests

# Install Supervisord
RUN apt-get -y install supervisor
RUN mkdir -p var/log/supervisor

# Configure Supervisord
COPY conf/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# bash
RUN sed -i s#/home/git:/bin/false#/home/git:/bin/bash# /etc/passwd

EXPOSE 8080 8082
CMD ["/usr/bin/supervisord"]
Run Code Online (Sandbox Code Playgroud)

在构建图像时,它在步骤23中失败,即

RUN mvn clean package -Pspark-1.6 -Phadoop-2.6 -DskipTests
Run Code Online (Sandbox Code Playgroud)

现在当我重建时,它开始从步骤23开始构建,因为docker正在使用缓存.

但是,如果我想从步骤21重建图像,即

RUN git clone https://github.com/apache/incubator-zeppelin.git
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?删除缓存的图像是唯一的选择吗?有没有其他参数可以做到这一点?

小智 40

一个解决方法:

  1. 找到要执行的步骤.
  2. 在那一步之前进行一个简单的虚拟操作,如"RUN pwd"

然后只需构建您的Dockerfile.它将从缓存中取出所有内容,然后在dummy命令之后执行这些行.

  • 我意识到这不是我需要的。它仅在更改后的第一次构建时有帮助......但在运行进一步构建时无济于事...... (3认同)
  • 这仅适用于编写 Dockerfile 的“快速而肮脏”的阶段,因为它是手动的并且只能运行一次,最终 @toms130 带有不断变化的虚拟参数的答案要好得多 (2认同)

BMi*_*tch 40

您可以通过执行操作来重建整个事物而无需使用缓存

docker build --no-cache -t user/image-name
Run Code Online (Sandbox Code Playgroud)

要强制从特定行开始重新运行,您可以传递一个未使用的arg.Docker将ARG值作为环境变量传递给RUN命令,因此更改ARG是对命令的更改,该命令会破坏缓存.甚至不需要在RUN线上自己定义它.

FROM ubuntu:14.04
MAINTAINER Samuel Alexander <samuel@alexander.com>

RUN apt-get -y install software-properties-common
RUN apt-get -y update

# Install Java.
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
RUN add-apt-repository -y ppa:webupd8team/java
RUN apt-get -y update
RUN apt-get install -y oracle-java8-installer
RUN rm -rf /var/lib/apt/lists/*
RUN rm -rf /var/cache/oracle-jdk8-installer

# Define working directory.
WORKDIR /work

# Define commonly used JAVA_HOME variable
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

# JAVA PATH
ENV PATH /usr/lib/jvm/java-8-oracle/bin:$PATH

# Install maven
RUN apt-get -y update
RUN apt-get -y install maven

# Install Open SSH and git
RUN apt-get -y install openssh-server
RUN apt-get -y install git

# clone Spark
RUN git clone https://github.com/apache/spark.git
WORKDIR /work/spark
RUN mvn -DskipTests clean package

# clone and build zeppelin fork, changing INCUBATOR_VER will break the cache here
ARG INCUBATOR_VER=unknown
RUN git clone https://github.com/apache/incubator-zeppelin.git
WORKDIR /work/incubator-zeppelin
RUN mvn clean package -Pspark-1.6 -Phadoop-2.6 -DskipTests

# Install Supervisord
RUN apt-get -y install supervisor
RUN mkdir -p var/log/supervisor

# Configure Supervisord
COPY conf/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# bash
RUN sed -i s#/home/git:/bin/false#/home/git:/bin/bash# /etc/passwd

EXPOSE 8080 8082
CMD ["/usr/bin/supervisord"]
Run Code Online (Sandbox Code Playgroud)

然后用一个独特的arg运行它:

docker build --build-arg INCUBATOR_VER=20160613.2 -t user/image-name .
Run Code Online (Sandbox Code Playgroud)

另外,我建议进行以下更改以使图层更小,RUN下载和安装后合并清除和删除单个命令的步骤越多,最终图像就越小.否则,您的图层将包含下载和清理之间的所有中间步骤:

docker build --build-arg INCUBATOR_VER=$(date +%Y%m%d-%H%M%S) -t user/image-name .
Run Code Online (Sandbox Code Playgroud)


小智 7

要完成Dmitry的回答,你可以使用uniq arg date +%s来保持相同的commanline

docker build --build-arg DUMMY=`date +%s` -t me/myapp:1.0.0
Run Code Online (Sandbox Code Playgroud)

Dockerfile:

...
ARG DUMMY=unknown
RUN DUMMY=${DUMMY} git clone xxx
...
Run Code Online (Sandbox Code Playgroud)


小智 7

另一种选择是删除要重建的缓存中间映像。

在构建输出中找到要重建的中间映像的哈希值:

Step 27/42 : RUN lolarun.sh
 ---> Using cache
 ---> 328dfe03e436
Run Code Online (Sandbox Code Playgroud)

然后删除该图像:

$ docker image rmi 328dfe03e436
Run Code Online (Sandbox Code Playgroud)

或者,如果它给您一个错误并且您可以强制执行它:

$ docker image rmi -f 328dfe03e436
Run Code Online (Sandbox Code Playgroud)

最后,重新运行您的构建命令,它将需要从该点重新启动,因为它不在缓存中。

  • @CharlieHaley 在这种情况下,您可以考虑删除子图像——这只是此步骤之后构建的下一个中间图像。 (2认同)

Ber*_*ard 5

一种更简单的技术。

Dockerfile:
在您要开始跳过缓存的位置添加此行。

COPY marker /dev/null

然后使用

date > marker && docker build .


red*_*dot 5

使用--cache-from=...选项并指定最后一层的哈希值以重用而无需重建。所有后续层都将被重建。

假设我有以下缓存的 docker 版本:

$ docker build -t pinger:latest .
Sending build context to Docker daemon  6.924MB
Step 1/5 : FROM ubuntu:latest
 ---> 58db3edaf2be
Step 2/5 : RUN echo "$(date)"
 ---> Using cache
 ---> b62b5deffedf
Step 3/5 : RUN apt-get update -y && apt-get install -y iputils-ping
 ---> Using cache
 ---> 02ba4da7d7a6
Step 4/5 : ENTRYPOINT ["ping"]
 ---> Using cache
 ---> dfd4c593d7be
Step 5/5 : CMD ["127.0.0.1"]
 ---> Using cache
 ---> 716cc6cbcf0e
Successfully built 716cc6cbcf0e
Successfully tagged pinger:latest
Run Code Online (Sandbox Code Playgroud)

现在,如果我想强制 apt-get 节重新运行:

$ docker build --cache-from=b62b5deffedf -t pinger:latest .
Sending build context to Docker daemon  6.924MB
Step 1/5 : FROM ubuntu:latest
 ---> 58db3edaf2be
Step 2/5 : RUN echo "$(date)"
 ---> Using cache
 ---> b62b5deffedf
Step 3/5 : RUN apt-get update -y && apt-get install -y iputils-ping
 ---> Running in 0d96737075a6
...
Run Code Online (Sandbox Code Playgroud)