Docker: интересные особенности базовых образов

  • Tutorial
Когда вы указываете в Dockerfile:
FROM ubuntu
то к вам на машину стягивается официально-поддерживаемый базовый образ Ubuntu (на сегодняшний день это 14.04 LTS). Мне стало интересно, чем образ этот отличается от «настоящей» чистой системы.

В процессе pull можно заметить, что он состоит из 5 слоёв:
docker pull ubuntu

ubuntu:latest: The image you are pulling has been verified
511136ea3c5a: Pull complete
3b363fd9d7da: Downloading 8.641 MB/197.2 MB 3m18s
607c5d1cca71: Download complete
f62feddc05dc: Download complete
8eaa4ff06b53: Download complete
Чтобы понять содержание каждого слоя, можно выполнить команду:

docker history --no-trunc ubuntu > history.txt

либо посмотреть исходный Dockerfile на GitHub. Каждый слой соответствует отдельной строке в Dockerfile:

511136ea3c5a — это отправная точка, пустой образ под названием scratch (строка FROM scratch).

3b363fd9d7da«вливание» официального образа Ubuntu из файла ubuntu-trusty-core-cloudimg-amd64-root.tar.gz

Далее начинается интересное.

607c5d1cca71длинная цепочка команд (команды рекомендуется объединять таким образом, чтобы не создавать большого количества слоёв, т.к. это чревато проблемами).

Остановимся здесь на минутку. Сначала добавляется скрипт policy-rc.d, который запрещает автоматический старт служб. Подробности можно прочитать в этой статье.

Именно поэтому вы наблюдаете в процессе билда:
invoke-rc.d: policy-rc.d denied execution of stop.
invoke-rc.d: policy-rc.d denied execution of start.
Следующая группа строк замещает файл /sbin/initctl. Цель этого изменения — заглушить предупреждение при попытке выполнить команду service:
Failed to connect to socket /com/ubuntu/upstart: Connection refused
В контейнерах upstart, естественно, не запущен (а в случае необходимости запуска нескольких служб рекомендуют Supervisor).

Делается это, на мой взгяд, кривовато: было бы проще заменить initctl ссылкой на /bin/true, но смысл не меняется. dpkg-divert указвыает, что initctl не надо перезаписывать при последующих установках обновлениий.

Далее следует конфигурирование установщика пакетов: отключение fsync для ускорения (в случае проблем всегда можно пересоздать контейнер с чистого листа), очистка кеша deb-файлов (он только занимает лишнее место в слоистой файловой системе), отключение установки переводов и активация сжатия индексов (не уверен, зачем именно это нужно).

f62feddc05dc — по непонятным причинам (вероятно, только для того, чтобы вставить комментарий) ещё одна команда вынесена из предыдущей цепочки. Данная строка активирует universe package source, правда не делает при этом apt-get update, так что перед установкой любого universe-пакета вам придется сделать update самим.

Наконец, последний слой выставляет /bin/bash в качестве команды по умолчанию.

Я подумал, что каждому, кто пользуется стандартными образами, полезно было бы знать, с чем именно он имеет дело. На этом пока что всё.
  • +54
  • 22,5k
  • 3
Поделиться публикацией
Ой, у вас баннер убежал!

Ну, и что?
Реклама
Комментарии 3
  • +4
    да не — нормальный пост
    • 0
      спасибо за разбор базового образа.
      на данный момент существует ряд подходов к работе с докером, в частности отключение ssh и т.д.
      более подробно можно почитать на английском у phusion, у них же есть базовый образ на основе последней ubuntu.
      • +2
        baseimage-docker не советую! Объясню почему:
        1. runit, используемый в качестве менеджера процессов, очень неудобен в использовании, особенно когда что-то идёт не так. Supervisord куда более приятен и к тому же сам умеет делать «reape unknown pid», так что «изобретения» в виде my_init не нужны.
        2. Ни ssh, ни nsenter теперь не являются необходимыми. Для входа в контейнер используется команда docker exec -ti CONTAINER_ID bash. Для более удобной работы в консоли внутри контейнера (запуск mc и тп.) рекомендую добавить в Dockerfile:
          ENV LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 TERM=xterm
          RUN locale-gen $LC_ALL
        3. Самое опасное: cron и logrotate пускаются со стандартными конфигами, не рассчитанными на работу в контейнерах. Пример: установили Apache, получили файл /etc/logrotate.d/apache2, внутри которого используется /etc/init.d, значит runit потеряет контроль над процессом после первой ротации логов.

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

      Самое читаемое