Почему наша работа внутри контейнера не должна изменять содержимое самого контейнера? - PullRequest
1 голос
/ 15 марта 2020

Я читаю статью , относящуюся к docker изображениям и контейнерам.

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

Но в то же время он говорит:

Ваш работа внутри контейнера не должна изменять контейнер. Как упоминалось ранее, файлы, которые необходимо сохранить после окончания срока службы контейнера, должны храниться в общей папке. Изменение содержимого работающего контейнера исключает преимущества, предоставляемые Docker. Поскольку один контейнер может отличаться от другого, внезапно ваша гарантия того, что каждый контейнер будет работать в любой ситуации, исчезнет.

Что я хочу знать, так это то, что является проблемой при изменении содержимого контейнера? Разве это не то, для чего предназначены контейнеры? где мы вносим свои собственные изменения, а затем создаем образ, который будет работать каждый раз. Даже если мы говорим об изменении самого содержимого контейнера, а не просто о добавлении каких-либо дополнительных пакетов, как это повредит чему-либо, поскольку изображение, созданное из этого контейнера, также будет иметь эти изменения, и другие контейнеры, созданные из этого образа, также унаследуют эти изменения.

Ответы [ 2 ]

1 голос
/ 15 марта 2020

Стандартный Docker рабочий процесс состоит из двух частей.

Сначала вы создаете образ:

  1. Проверьте соответствующее дерево исходных кодов в выбранной вами системе управления версиями.
  2. Если необходимо, запустите какой-то процесс предварительной сборки (скомпилируйте ресурсы c, создайте файл Java .jar, запустите Webpack, ...).
  3. Запустите docker build, который использует инструкции из Dockerfile и содержимое дерева локальных исходных кодов для создания изображения.
  4. При необходимости docker push полученное изображение в репозиторий Docker (Docker Hub, что-то в облаке, что-то частное).

Затем вы запускаете контейнер на основе этого образа:

  1. docker run имя образа из сборки фаза. Если он еще не находится в локальной системе, Docker извлечет его из хранилища для вас.

Обратите внимание, что вам не нужно локальное дерево исходных текстов только для запуска образа; Достаточно иметь изображение (или его имя в хранилище, которое вы можете найти). Точно так же в этом рабочем процессе нет «получить оболочку» или «запустить службу», просто docker run само по себе должно все поднять.

(В этом смысле полезно думать об изображении одинаково как вы думаете о веб-браузере. Вы не загружаете исходный код Chrome для его запуска и никогда не «получаете оболочку» в своем веб-браузере; он почти всегда предварительно компилируется, и вам не нужен доступ к его источнику, или, если вы это сделаете, у вас есть реальная среда разработки для работы с ней.)

Теперь: представьте, что есть некоторая критическая широко распространенная уязвимость безопасности в некотором основном программном обеспечении, используемом вашим приложением (у OpenSSL была пара, например). Достаточно заметно, что все базовые образы Docker уже обновлены. Если вы используете этот рабочий процесс, обновление вашего приложения очень простое: проверьте исходное дерево, обновите строку FROM в Dockerfile до чего-то более нового, перестройте, и все готово.

Обратите внимание, что ни один из этих рабочих процессов не «вносит произвольные изменения в контейнер и фиксирует его». Когда вы вынуждены перестраивать образ на новой базе, вы действительно не хотите находиться в положении, когда исполняемый бинарный файл - это что-то, что кто-то создает вручную, редактируя контейнер, но с тех пор он ушел компании, и нет записи о том, что они на самом деле сделали.

Короче: никогда запустить docker commit. Хотя docker exec является полезным инструментом отладки, он не должен быть частью вашего основного рабочего процесса Docker, и если вы регулярно запускаете его для настройки контейнеров или думаете о его написании сценариев, лучше попробовать перенести эту настройку вместо обычного запуска контейнера.

1 голос
/ 15 марта 2020

Рассматривать файловую систему контейнера как эфемерную. Вы можете изменять его по своему усмотрению, но когда вы его удаляете, внесенные вами изменения пропадают.

Это основано на объединенной файловой системе, наиболее популярной / рекомендуемой из которых является overlay2 в текущих выпусках. Наложенная файловая система объединяет несколько нижних слоев изображения с верхним слоем контейнера. Чтение будет выполняться через эти слои до тех пор, пока не будет найдено совпадение, либо в контейнере, либо в файловой системе изображения. Запись и удаление выполняются только на уровне контейнера.

Поэтому, если вы устанавливаете пакеты и вносите другие изменения, когда контейнер удаляется и воссоздается из того же изображения, вы возвращаетесь в исходное состояние изображения без каких-либо ваших изменений, включая новый / пустой слой контейнера в оверлейной файловой системе.

Из рабочего процесса разработки программного обеспечения вы хотите упаковать и выпустить изменения в двоичные файлы и зависимости приложения как новые образы, и эти образы должны быть создан с Dockerfile. Постоянные данные должны храниться в томе. Конфигурация должна быть введена как файл, переменная среды или параметр CLI. И временные файлы в идеале должны быть записаны в tmpfs, если эти файлы не являются большими. Когда все сделано таким образом, можно даже сделать root FS контейнера доступным только для чтения, исключив большую часть атак, основанных на внедрении кода для запуска внутри файловой системы контейнера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...