Что делать, если ваш файл Dockerfile становится настолько большим, что его невозможно поддерживать

Когда размер Dockerfile превышает разумный предел, возникает несколько проблем:

  • Его сложно понять и поддерживать - нам нужно прочитать сотни строк, чтобы понять все зависимости.
  • Между столькими строками можно упустить явную проблему безопасности.
  • Git вызовет больше конфликтов, поскольку все меняют один и тот же файл
  • Если мы не очистим каждую зависимость, это может привести к тяжелому изображению

Лучшее решение - разделить наш Dockerfile на несколько Dockerfiles, чтобы наши Dockerfile были меньше по размеру и их было легче понять и поддерживать.

Вот несколько советов по уменьшению размера вашего Dockerfile.

Рефакторинг 1: извлечение зависимости из официального образа

Избегайте создания артефактов, скопированных с официального изображения.

Пример

Оригинал:

FROM golang:1.12
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git openssh-client zip
WORKDIR $GOPATH/src/github.com/hashicorp/terraform
RUN git clone https://github.com/hashicorp/terraform.git ./ && \
    git checkout v0.12.9 && \
    ./scripts/build.sh
WORKDIR /my-config
COPY . /my-config/
CMD ["terraform init"]

Рефакторинг:

FROM hashicorp/terraform:0.12.9 AS terraform
FROM golang:1.12
COPY --from=terraform /go/bin/terraform /usr/bin/terraform
WORKDIR /my-config
COPY . /my-config/
CMD ["terraform init"]

Рефакторинг 2: извлечение зависимости в другой док-файл

Когда нет официального образа, из которого можно извлечь артефакт, вам следует отделить его сборку в другом Dockefile.

Затем скопируйте артефакты в исходный файл Dockerfile.

Пример

Оригинал:

FROM golang:1.12
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git openssh-client
WORKDIR /go/src/gitlab.com/sahilm/
RUN git clone https://github.com/sahilm/yamldiff.git
RUN cd yamldiff && \
    go get -u github.com/golang/dep/cmd/dep && \
    dep ensure && \
    GOOS=linux go build -o /usr/local/yamldiff
WORKDIR /my-app
COPY . /my-app/
CMD ["./run.sh"]

Рефакторинг:

Dockerfile для yamldiff:

FROM golang:1.12
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git openssh-client
WORKDIR /go/src/gitlab.com/sahilm/
RUN git clone https://github.com/sahilm/yamldiff.git
RUN cd yamldiff && \
    go get -u github.com/golang/dep/cmd/dep && \
    dep ensure && \
    GOOS=linux go build -o /usr/local/yamldiff
CMD ["bash"]

Dockerfile для моего приложения:

FROM Marvalero/yamldiff:latest AS yamldiff
FROM golang:1.12
COPY --from=yamldiff /usr/bin/yamldiff /usr/bin/yamldiff
WORKDIR /my-app
COPY . /my-app/
CMD ["./run.sh"]

Рефакторинг 3: разделите изображение на этапы

Docker имеет многоступенчатую функцию, которая пригодится, когда ваш Dockerfile состоит из разных частей.

Наиболее распространенный вариант использования - выполнить этап сборки и затем скопировать артефакты в основное изображение. Наличие разных этапов делает ваш Dockerfile более понятным и безопасным.

Пример

Оригинал:

FROM golang:1.12
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git openssh-client
WORKDIR /go/src/gitlab.com/sahilm/
RUN git clone https://github.com/sahilm/yamldiff.git
RUN cd yamldiff && \
    go get -u github.com/golang/dep/cmd/dep && \
    dep ensure && \
    GOOS=linux go build -o /usr/local/yamldiff
CMD ["bash"]

Рефакторинг:

FROM golang:1.12 as Builder
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git openssh-client
WORKDIR /go/src/gitlab.com/sahilm/
RUN git clone https://github.com/sahilm/yamldiff.git
RUN cd yamldiff && \
    go get -u github.com/golang/dep/cmd/dep && \
    dep ensure && \
    GOOS=linux go build -o /usr/local/yamldiff
FROM ubuntu:18.04
COPY --from=Builder /usr/local/yamldiff /usr/local/yamldiff
CMD ["bash"]

Рефакторинг 4: сортировка многострочных аргументов

По возможности отсортируйте многострочные аргументы. Это помогает еще раз проверить, не дублируется ли пакет.

Пример

Оригинал:

FROM ubuntu:18.04
RUN apt-get -yqq install \
    ca-certificates \
    bash \
    jq \
    wget \
    curl \
    openssh-client \
    build-essential \
    libpng-dev \
    python \
    zip
CDM ["bash"]

Рефакторинг:

FROM ubuntu:18.04
RUN apt-get -yqq install \
    bash \
    build-essential \
    ca-certificates \
    curl \
    jq \
    libpng-dev \
    openssh-client \
    python \
    wget \
    zip
CDM ["bash"]

Рефакторинг 5: Теги

Поддержание чистоты ваших тегов также важно при работе с образами Docker. Я всегда считаю очень полезным иметь три типа тегов:

  • Название ветки: определяет последнюю версию моего изображения для конкретной ветки.

Примечание. Почему бы не использовать latest? При использовании latest я никогда не знаю, означает ли это последнюю стабильную версию или последнюю сборку во всем репозитории. Использование имен веток (например, master, feature/new-class и т. Д.), Указывающих на последнюю версию ветки, является более интуитивным.

  • Версия: требуется, чтобы отличать исправления от критических изменений. Я рекомендую использовать семантическое управление версиями (major.minor.patch).
  • Фиксация: я всегда хочу знать, на какую фиксацию указывает тег. Теперь вы можете сделать это, создав теги версий в своем репозитории. Но когда это невозможно, просто пометьте свои изображения его Commit SHA.

Наслаждайтесь красивыми файлами Docker

Спасибо за прочтение. Надеюсь, вам станет проще поддерживать файлы Dockerfiles.

Если вы хотите узнать больше о Docker и контейнерах, вы можете ознакомиться с двумя моими предыдущими статьями: