Сетевая подсистема docker является pluggable (подключаемой/модульной) и использует драйверы.
Driver
Description
bridge
Default network driver. Используется, если контейнеру нужно общаться с другими контейнерами на одном хосте. См. Bridge network driver
host
Убирает сетевую изоляцию между контейнером и хостом docker, используя сетевые возможности хоста напрямую. См. Host network driver
none
Fully изолирует контейнер от хоста, других контейнеров. См. None network driver
overlay
Оверлейные сети соединяют несколько демонов docker вместе, что, кстати, избавляет от необходимости маршрутизации на уровне ОС. См. Overlay network driver
macvlan
Сети macvlan позволяют назначить MAC-адрес контейнеру, чтобы он выглядел как физическое устройство внутри сети. Docker daemon направляет трафик к контейнерам по их MAC-адресам. Используется для работы с устаревшими приложениями или для миграции с виртуальных машин. См. Macvlan network driver
ipvlan
Сети IPvlan предоставляют юзерам total control над адресацией IPv4 и IPv6. Короче, см. IPvlan network driver
Другие инструкции создают временные промежуточные образы, не увеличивая размер сборки.
Эффективнее следовать правилу Use multi-stage builds, что также позволит включать инструменты и debug-операции в промежуточные этапы сборки, не влияя на конечный образ.
Нужно писать максимально эфемерные контейнеры. Подразумевается возможность остановки, уничтожения контейнера, его последующей перестройки и замены с минимальными настройками.
Don’t use docker commit on a running container
Не создавай образы из запущенных контейнеров — применяй docker commit только к остановленному контейнеру, иначе получившийся (некорректный) образ не будет воспроизводимым.
Don’t COPY symlinks
Симлинки не резолвятся в Dockerfile. Не пытайся в Dockerfile передать симлинки через инструкцию COPY — that’s not gon work.
Я это правило объединил со схожим: “Don’t run more than one process in a container”
Придерживайся (UNIX-way) идеи “Один контейнер — один процесс”. Пусть лучше будет несколько общающихся между собой контейнеров, что сохранит преимущества контейнеров (согласно философии контейнеров) и:
При запуске docker buildтекущая директория называется build context. По умолчанию предполагается, что Dockerfile находится в текущей директории, но через -f/--file можно указать другое местоположение. Независимо от того, где находится указанный Dockerfile, всё рекурсивное содержимое текущей директории передастся docker daemon-у в качестве контекста сборки.
Build context example
mkcd myproject<<< 'hello' > hello
Dockerfile
FROM busyboxCOPY /hello /RUN cat /hello
docker build -t hello-app:v1 .
Теперь раскинь Dockerfile и helloпо разным директориям:
Используй .dockerignore для исключения файлов, не относящихся к сборке — не нужно менять структуру репозитория с помощью .gitignore.
Шаблоны исключения .dockerignore аналогичны .gitignore.
Многоступенчатые сборки позволяют уменьшить размер конечного образа.
ПоделиDockerfile на отдельные этапы так, что итоговый результат (конечный образ) содержит только необходимые для работы приложения файлы.
Example
dockerfile
## First stageFROM node:14 AS builderWORKDIR /appCOPY package*.json ./RUN npm installCOPY . .RUN npm run build## Second stageFROM nginx:alpine# Copying the built app from the first stageCOPY--from=builder /app/dist /usr/share/nginx/htmlCOPY nginx.conf /etc/nginx/conf.d/default.confEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
Для каждой инструкции docker проверяет возможность использования инструкции из кэша сборки.
docker аннулирует кэш для измененных слоев. Например, изменение файла, который тянется в образ с помощью ADD или COPY заставит docker аннулировать кэш для этого слоя и запустить ADD или COPYзаново. И если слой изменился, это затронет и все следующие слои — все последующие слои также будут запущены заново (даже если последующие слои не будут собираться по-другому, их все равно нужно запустить заново).
Если несколько образов юзают общие компоненты — создай reusable stage и основывай уже на нем уникальные стадии, чтобы docker-у нужно было собрать общую стадию только один раз. Это сделает производные образы эффективнее в утилизации памяти и быстрее при загрузке — в общем, те же code reuse pros.
Если разделить эти команды на разные RUN инструкции, то в будущем при добавлении, например, новых пакетов для установки docker build может не запустить apt-get update, а использовать кэшированный слой для этой инструкции, что приведет к тому, что пакеты не установятся или установятся их неактуальные версии.