Рас­па­ков­ка Docker, часть 3

Редактура Вадим Макеев

Во второй части мы рассмотрели практические примеры упаковки приложений. В этой заключительной части мы рассмотрим способы использования Docker в процессе самой разработки.

НавигацияСкопировать ссылку

Код внутри контейнераСкопировать ссылку

До сих пор, мы не говорили о написании кода внутри контейнера. Вы можете использовать классическую связку vim с плагинами + tmux. Вы можете подключится к контейнеру по SSH почти из любой популярной среды разработки. Но не использовать или хотя бы не попробовать использовать возможности Visual Studio Code (VS Code) будет преступлением.

Для того, чтобы работать с кодом красиво, можно и даже нужно использовать Visual Studio Code Remote, что позволяет подключиться к созданному контейнеру и работать с ним в терминальном режиме.

Это делается довольно просто. Достаточно установить расширение Remote Development и создать файл .devcontainer.json в папке из которой собирается ваш контейнер. Часто эта папка является папкой проекта. Можно собрать контейнер и на ходу с помощью мастера, но это трудно воспроизвести впоследствии. Например, содержимое .devcontainer.json может быть таким:

{
    "name": "server",
    "dockerComposeFile": ["../docker-compose.yaml"],
    "service": "test",
    "workspaceFolder": "/app"
}

Это заставит VS Code собрать все контейнеры, указанные в файле для Docker Compose и открыть папку /app, которая находится внутри контейнера server.

В VS Code можно попытаться открыть папку проекта, и среда сама предложит открыть снова ее, но уже внутри контейнера. А можно сделать это вручную, нажав клавишу F1 или сочетание клавиш Ctrl + P (Cmd + P для macOS) и выбрав команду:

> Remote-Containers: Open Workspace in Container.

Вы также можете указать те расширения, которые нужно поставить для данной рабочей сессии VS Code. После работы все эти расширения удаляться из редактора. Это очень удобно. Мне это позволяет держать в VS Code всего десять (!) расширений, которые будут востребованы в любом проекте, и никаких расширений для конкретного языка или фреймворка. Чистота и порядок!

В списке литературы вы сможете познакомится с репозиторием конфигурационных файлов для разных языков и фреймворков, на которых я в основном и работаю. Этот репозиторий обновляется по мере необходимости.

Тестирование приложений в GUIСкопировать ссылку

В Docker можно запускать не только консольные приложения, но и приложения с графическим интерфейсом (GUI). Единственное ограничение — они будут работать на сервере системы X Windows для рендеринга графических приложений и взаимодействия с ними. Воспользоваться можно интересным свойством приложений с графическим интерфейсом Linux. Приложения запускаются как клиенты, которые обращаются к серверу X Windows. При этом не важно, где этот сервер расположен. Он вполне может быть на удаленном хосте. А нам это и надо!

Если вы работаете на любом дистрибутиве ОС Linux, такой сервер у вас уже запущен. Чтобы поставить его на macOS, можете воспользоваться XQuartz. На ОС Windows можно попробовать использовать VcXsrv. В первую очередь вы должны разрешить удаленное подключение к X Windows серверу и добавить переменные среды для контейнера. Универсального решения для всех ОС не существует, но я приведу флаги для команды docker run, учитывая ОС:

-e DISPLAY=docker.for.mac.host.internal:0 # macOS
-e DISPLAY=host.docker.internal:0 # Windows
--net=host -e DISPLAY=:0 # Linux

Цифра в конце строки обозначает номер монитора, на который будет выведен графический интерфейс приложения (0 используется для обозначения главного монитора). Для macOS и Windows вы можете воспользоваться графическим интерфейсом вашего сервера. Удаленное подключение для LInux можно разрешить с помощью команды:

xhosts +

Например, вы так можете запустить Gimp одной командой:

  • macOS: docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 jamesnetherton/gimp
  • Windows: docker run --rm -ti -e DISPLAY=host.docker.internal:0 jamesnetherton/gimp
  • Linux: docker run --rm -ti --net=host -e DISPLAY=:0 jamesnetherton/gimp

Для запуска Eclipse нужно в конце дописать psharkey/eclipse вместо jamesnetherton/gimp, а чтобы запустить Firefox — jess/firefox. В конце строки вы указываете имя нужного образа, который будет скачан с Docker Hub? Посмотрите, как был собран один из них, и вы будете точно знать, как запустить необходимое вам приложение с графическим интерфейсом.

Безопасность DockerСкопировать ссылку

Предлагаю обсудить еще одну важную тему — безопасность. Рассмотрим четыре аспекта:

  1. Безопасность вашей ОС во время разработки;
  2. Управление доступом на этапе запуска приложения в контейнере;
  3. Безопасные образы;
  4. Хранение секретной информации.

Безопасность вашей ОССкопировать ссылку

Что мешает ОС быть в безопасности? Конечно то, что вы вынуждены устанавливать кучу разнообразного софта, в том числе и экспериментального. Это могут быть приложения с графическим интерфейсом или сугубо консольные приложения. Часто вам нужно устанавливать JVM или что-то подобное. Каждая новая программа несет в себе дырки, через которые можно что-нибудь, да сделать. Docker позволяет практически избавить вас от необходимости установки этого груза. Да и работать с коллегами будет намного проще.

Доступ при запуске приложенияСкопировать ссылку

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

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

docker run -u user image

Вы также можете добавить эту настройку в Dockerfile:

FROM alpine:latest
RUN apk update && apk add --no-cache git
USER 1000

Во-вторых, необходимо поддерживать только те возможности, которые вам нужны. Полный функционал для вашего приложения внутри контейнера зачастую совершенно не обязателен. Управление возможностями осуществляется через командную строку с помощью параметров --cap-drop и --cap-add. Лучшей практикой будет запуск контейнера с одним параметром --cap-drop all и разрешающими флагами для необходимых возможностей, обеспечивающих работу вашего приложения. Вы можете ознакомиться подробнее со всеми поддерживаемыми флагами в документации. С помощью Docker Compose вы также можете управлять поддержкой той или иной возможности контейнера с помощью параметров cap_drop и cap_add. В документации к Linux есть исчерпывающий список.

В-третьих, необходимо управлять ресурсами вашей ОС, которые будут доступны для запуска контейнеров. Если вы не будете ограничивать эти ресурсы, Docker просто забьет всю оперативную память, что очень смахивает на DDOS атаку прямо у вас на компьютере. Необходимо также ограничивать и использование процессора. В Windows и macOS вы можете посмотреть потребление ресурсов системы с помощью Docker Desktop. Это можно сделать и через консоль командой, доступной уже на всех ОС:

docker stats

Об оптимальных настройках вы можете подробнее почитать в официальной документации.

Безопасные образыСкопировать ссылку

Во время работы вы часто будете использовать образы из разных реестров. Будьте бдительны! Использовать образы необходимо с большим количеством скачиваний, высоким рейтингом при большом количестве отзывов, рекомендованные компанией (официальные образы) или группой, которой вы доверяете. Загружая неизвестный образ, вы получаете кота в мешке. В любом случае внимательно смотрите на конфигурационные файлы и базовые образы. Желательно также использовать подписанные образы. Для того чтобы уберечь себя от загрузки «неправильных» образов, необходимо выполнить команду в терминале:

export DOCKER_CONTENT_TRUST=1

Прочитать подробнее про эту систему можно в документации.

Хранение секретной информацииСкопировать ссылку

Чтобы учетные данные аккаунтов, сертификаты, секретные ключи доступа, имена ресурсов и любая другая конфиденциальная информация оставались в тайне от других, необходимо следовать двум правилам:

  1. Не помещайте секреты внутрь образа;
  2. Не используйте для секретов переменные среды.

В документации Docker есть специальный раздел, посвящённый сохранности подобной чувствительной информации. Там предлагаются различные варианты. Но Джеф Хэйл (Jeff Hale) советует хранить секретные данные в томах (Docker volumes), создание и использование которых были описаны выше.

ЗаключениеСкопировать ссылку

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

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

Если вы поработаете с Docker, вас, скорее всего, от него уже не спасти. Есть надежда, что вы будете писать уже следующее приложение внутри контейнера. В заключение, вот вам ещё несколько ссылок:

Материалы по темеСкопировать ссылку

  1. Современные операционные системы
  2. Anatomy of Docker
  3. LXC vs Docker: Why Docker is Better
  4. A Beginner-Friendly Introduction to Containers, VMs and Docker
  5. Изучаем Docker, часть 1: основы
  6. Изучаем Docker, часть 2: термины и концепции
  7. Википедия: Стандартные потоки
  8. Википедия: TTY-абстракция
  9. Manage data in Docker
  10. Изучаем Docker, часть 6: работа с данными
  11. Dockerfile reference
  12. Изучаем Docker, часть 3: файлы Dockerfile
  13. Postgres: Dockerfile
  14. Linux downloads (Red Hat family)
  15. Docker run reference
  16. Top 14 Best PHP CMS In Market For Developers in 2020
  17. Install Docker Compose
  18. Compose file version 3 reference
  19. Интегрируем Docker в приложение Vue.js
  20. Официальный репозиторий Node.js от команды Docker
  21. Изучаем Docker, часть 4: уменьшение размеров образов и ускорение их сборки
  22. Use multi-stage builds
  23. Utilizing the power of Docker while building MERN Apps using mern-docker
  24. How To Set Up Flask with MongoDB and Docker
  25. Изучаем Docker, часть 5: команды
  26. Docker Commands — The Ultimate Cheat Sheet
  27. Docker Seeds
  28. Docker для начинающего разработчика

Видео по темеСкопировать ссылку

  1. The future of Linux Containers
  2. Основы Docker. Большой практический выпуск