Перестроить изображение докера с определенного шага

У меня есть ниже Dockerfile.

FROM ubuntu:14.04
MAINTAINER Samuel Alexander <[email protected]>

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"]

При создании изображения это не удалось на этапе 23, то есть

RUN mvn clean package -Pspark-1.6 -Phadoop-2.6 -DskipTests

Теперь, когда я перестраиваю его, он начинает строить с шага 23, когда докер использует кеш.

Но если я хочу перестроить изображение с шага 21, то есть

RUN git clone https://github.com/apache/incubator-zeppelin.git

Как я могу это сделать? Удаление кэшированного изображения является единственным вариантом? Есть ли дополнительный параметр для этого?

Ответ 1

Вы можете восстановить всю вещь без использования кэша, выполнив

docker build --no-cache -t user/image-name

Для принудительного повторного запуска, начиная с определенной строки, вы можете передать аргумент, который в противном случае не используется. Docker передает значения ARG в качестве переменных среды вашей команде RUN, поэтому изменение ARG - это изменение команды, которая нарушает кэш. Нет необходимости определять его самостоятельно на линии RUN.

FROM ubuntu:14.04
MAINTAINER Samuel Alexander <[email protected]>

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"]

А затем просто запустите его с уникальным аргументом:

docker build --build-arg INCUBATOR_VER=20160613.2 -t user/image-name .

Чтобы изменить аргумент при каждой сборке, вы можете передать метку времени как arg:

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

или же:

docker build --build-arg INCUBATOR_VER=$(date +%s) -t user/image-name .

Кроме того, я бы порекомендовал следующие изменения, чтобы ваши слои были меньше, чем больше вы можете объединить этапы очистки и удаления одной командой RUN после загрузки и установки, тем меньше будет ваш окончательный образ. В противном случае ваши слои будут включать все промежуточные этапы между загрузкой и очисткой:

FROM ubuntu:14.04
MAINTAINER Samuel Alexander <[email protected]>

RUN DEBIAN_FRONTEND=noninteractive \
    apt-get -y install software-properties-common && \
    apt-get -y update

# Install Java.
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
    add-apt-repository -y ppa:webupd8team/java && \
    apt-get -y update && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get install -y oracle-java8-installer && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    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 && \
    DEBIAN_FRONTEND=noninteractive \
    apt-get -y install 
      maven \
      openssh-server \
      git \
      supervisor && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

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

# clone and build zeppelin fork
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

# Configure Supervisord
RUN mkdir -p var/log/supervisor
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"]

Ответ 2

Один обходной путь:

  • Найдите шаг, из которого вы хотите выполнить.
  • Перед этим шагом ставьте простую манекенную операцию типа "RUN pwd"

Затем просто создайте файл Dockerfile. Это займет все до этого шага из кеша, а затем выполнит строки после команды dummy.

Ответ 3

Чтобы ответить на вопрос Дмитрия, вы можете использовать uniq arg, как date +%s, чтобы всегда хранить один и тот же commanline

docker build --build-arg DUMMY=`date +%s` -t me/myapp:1.0.0

Dockerfile:

...
ARG DUMMY=unknown
RUN DUMMY=${DUMMY} git clone xxx
...

Ответ 4

Более простая техника.

Dockerfile:
Добавьте эту строку там, где вы хотите, чтобы кэширование начиналось с пропуска.

COPY marker/dev/null

Затем построить с помощью

date > marker && docker build.

Ответ 5

Если место ARG INCUBATOR_VER=unknown сверху, то кеш не будет использоваться в случае изменения INCUBATOR_VER из командной строки (только что протестировал сборку). Для меня работало:

# The rebuild starts from here
ARG INCUBATOR_VER=unknown
RUN INCUBATOR_VER=${INCUBATOR_VER} git clone https://github.com/apache/incubator-zeppelin.git