Build and run your image

Робота над ашипками

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

VasilioRuzanni:

  1. Ubuntu не спроектирована для работы в контейнере.

    Базовый образ убунты в docker’е это ее с правильно выключенным init и затюненным dpkg. Получается, что таки допроектировали. Для старых добрых OpenVZ контейнеров убунту тоже приходилось допиливать, и ничего, жили и живем годами в продакшне.

  2. Нет init — будут зомби.

    Да, зомби всё еще копятся. Если запустить fork-бомбу, то через 10 секунд на хост-машину с docker’ом уже не папость по SSH: can’t fork. К чести docker’а, запуск покажет все запущенные контейнеры, а погасит бомбу и порипает всех зомби.

    Однако, как часто бывает, если хотеть что-то сломать, то что-то таки сломается. Если в вашем приложении воркеры действительно часто внезапно мрут, ожидая завершения дочернего процесса, то у меня для вас плохие новости. Если же вы в таком поведении воркеров не видите ничего плохого, то дались вам эти зомби? Если же частые разрывы в иерархии процессов у вас by design, то да, стоит посмотреть в сторону, например, tini.

  3. Syslog?

    Так как docker предполагает, что микросервис шлет свои логи в STDOUT и STDERR, syslog не нужен. Docker сам управляет логами, и позволяет их сразу слать на анализ без сохранения. Если хотите хранить, то, во-первых, это не по облачному феншую, а во-вторых, логи таки могут занять весь диск.

  4. Cron?

    Что простите? А дженкинс нам на что? Как можно юзать крон в 2016 году? Однако, иногда очень-очень хочется, и, стоит надеяться, что docker инкапсулирует запуск сервисов по времени в самого себя. Но и сейчас никто не мешает запустить контейнер с произвольной реализацией крона и запускать контейнеры из него.

  5. SSH?

    По сути, консольная утилита уже и есть SSH. Она связывается с демоном по зашифрованному соединению, аутентифицируется по ключу, запускает шел и эмулирует терминал. Есть даже аналог scp.

  6. Неправда, что docker рассчитан на запуск только одного процесса на контейнер!

    Неправда, что неправда!

  7. А давайте сделаем из непривычного docker’а привычный OpenVZ.

    А давайте без давайте.

powerman:

Приличный тред получился.

Во-первых, если у вас живое приложение, то не будет никаких проблем с обновлением любого софта, и не только «пакетов ОС», а еще и версий фреймворков, баз данных, хитрожёлтых самопальных зависимостей, и еще чего угодно. Взяли — и пересобрали.

А во-вторых, работу с «пакетами ОС», если они на самом деле используются в каком-то вашем микросервисе, надо при обновлении тестировать. А готовить новый релиз к тестированию в мире docker’а принято с помощью — подожди-подожди — пересборки.

И главное, спросите любого владельца маломальски прибыльного сайта, что ему важнее: hardened gcc (с PIE и SSP) и потенцально невзламываемая до следующего shellshock интернет-шаурмятня или мгновенный выкат новой версии приложения без «этого тупого бага с оплатой», уносящего по 100500 денег в час?

Можно взглянуть на безопасность из будущей статьи про микросервисы. Современный сервер состоит из приложения и системы. Обе части надо защищать и обновлять. В предельном случае, к которому стремится сообщество docker’а, в контейнере не будет системы, а только приложение. И это приложение должно делать только одну функцию, например CQRS из базы данных. Тогда паника админов по поводу плохого базового образа убунты бесследно проходит, так как убунты в контейнере больше нет.

grossws:

Прошу всех читателей не воспринимать —link, как секьюрный оверлей, и сам не буду. Если ваше приложение перезрело приватное облако в одном датацентре и дозрело до распределенного по глобусу монстра, пожалуйста, настройте шифрование.

@админы:

Рекомендую почитать «Механическое пианино» Воннегута. За известным исключением, все профессии, однажды, теряют свою маржу.

Scf:

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

Fesor:

Shared memory подразумевает выполнение процессов на одной машине. Если эти два процесса запущены на одном ядре, как в случае docker’а, то им достаточно иметь доступ к одному и тому же файлу (один inode в файловой системе), чтобы расшарить память. Рецепт для docker’а очень прост: делаете файлу из общего volume’а и всё.

Полезно помнить, что docker всего лишь скрывает процессы друг от друга, но от этого они не перестают быть обычными юниксовыми процессами в обычной юниксовой среде.

JPEG:

Назад к основам

Как часто бывает, в какой-то момент состояние некой системы становится неуправляемым и требует новых технологий. В программировании, правда, часто выходит наоборот — требуется вспомнить старые технологии. Вот и в случае с docker’ом не случилось ничего нового: взяли принципы функционального программирования (другие видят ООП) и микроядерности, применили к инфраструктурному слою приложения (серверам, сети и т.п.) и получили stateless-иммутабельные-изолированные-микросервисы. Все прелести docker’а вырастают именно из этого. Как известно, функциональщина не так проста, как хотел бы Рич Хикки. Чтобы можно было каждый день пользоваться мудростью предков, нужно иметь хорошие инструменты. Docker как раз и есть такой инструмент.

Вот базовые отличия docker-контейнера (не микросервиса, см. выше) от простого сервера.

Стейтлес

Конфигурация контейнера не может и не должна меняться после запуска. Все предварительные работы делаются на этапе создания образа или старта контейнера: конфиги, порты, общие папки, переменные окружения, всё это должно быть известно к моменту старта контейнера. Конечно, docker позволяет запущенному внутри контейнера процессу делать со своей памятью и файловой системой всё что тому заблагорассудится, но трогать что-то, что можно было потрогать до запуска считается плохим тоном.

Чистый (pure)

Контейнер ничего не знает о хост системе и не может мешать другим контейнерам: ни влезть в чужую файловую систему, ни послать сигнал чужому процессу, ни даже в случайный порт стукнуться. На то он и контейнер. Само собой, docker позволят контейнерам общаться, но только строго задекларированными способами. Еще можно запускать контейнеры наделенные какими-нибудь суперсилами, например, доступом к реальной сети или физическим девайсам.

Ленивый

При запуске контейнер не копирует файловую систему образа, из которого создан. Контейнер всего-лишь создает пустую файловую систему поверх образа. В docker’е это называется слоем. Так же устроены и образы. Образ состоит из списка (геологических) слоев, накладывающихся друг на друга. Отсюда такая высокая скорость запуска нового контейнера: меньше секунды.

Декларативный

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

Функциональный

Контейнер делает только одно дело, но делает его хорошо. Предполагается, что в контейнере будет жить всего один процесс (можно с семьёй), выполняющий всего одну функцию в приложении. За счет того, что в контейнере нет своего ядра, загрузочного раздела, init-процесса и, чаще всего, даже пользователь всего один (псевдо-root) — то есть в контейнере нет полноценной операционной системы — за счет отсутствия всего этого контейнер стартует так быстро, как стартовал бы ваш сервис будь операционная система уже полностью загружена. Это узкая специализация делает функцию реализуемую контейнером предсказуемой и масштабируемой. Так как процесс только один, ему неоткуда ждать (если только снаружи) переполнения логов, попадания в своп и тому подобного.

Строгий

По-умолчанию, docker запрещает контейнеру всё, кроме доступа в сеть (которую тоже можно запретить). Однако, при необходимости позволяется нарушать любые эти правила, когда нарушить правила бывает логичнее. И что интересно, разрешать доступ также просто, как и запрещать. Соединять или разъединять контейнеры в docker’е с каждой версией становится всё проще и проще, особенно радует работа с сетью, распределенной по датацентрам.

Часть 0.1 Сравнение с VM

  1. независимость — контейнер может быть перемещен на любую ОС с docker-службой на борту и контейнер будет работать. (Официально — да, по факту, не уверен что совместимость такая радужная, как пони, радуга и бабочки. Если у вас есть иной опыт — прошу поделиться)
  2. самодостаточность — контейнер будет выполнять свои функции в любом месте, где бы его не запустили.
  1. Внутри контейнера находится минимально необходимый набор софта, необходимый для работы вашего процесса. Это уже не полноценная ОС, которую надо мониторить, следить за остатком места итд итп.
  2. Используется другой подход к виртуализации. почитать об этом. Я имею ввиду сам прицип — там нет привычной хостовой ОС.
  3. Следует особо относиться к контейнеру и генерируемым им данным. Контейнер это инструмент обработки данных, но не инструмент их хранения. Как пример — контейнер — это гвоздезабивающая машина, подаваемые на вход данные — доска и гвоздь, результат работы — забить гвоздь в доску. При этом доска с гвоздем не остается частью той самой гвоздезабивающей машины, результат отдельно, инструмент отдельно. Выходные данные не должны сохраняться внутри контейнера (можно, но это не docker-way). Поэтому, контейнер это либо worker (отработал, отчитался в очередь), либо, если это, например, веб-сервер, то нужно использовать внешние тома. (все это очень просто, не стоит в этом моменте грустить).

I have new developers to onboard.

Regardless of an organization’s size, onboarding new developers and getting them up to speed as quickly as possible remains a distinct challenge. Using Docker Desktop and Docker Compose, you can significantly reduce local development environment setup times and quickly onboard your developers so they can be productive right away. Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you can easily create and start all the services from your configuration.

Упрощаем с docker

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

Рассмотрим тривиальный Qt проект, который собирается с помощью qmake — SimpleQtProject. В папке docker указанного проекта находится ряд файлов:

  • centos7.docker — описывает контейнер для сборки проекта под CentOS 7;
  • ubuntu-bionic.docker — контейнер для сборки под Ubuntu 18.04;
  • ubuntu-xenial.docker — описывает контейнер для сборки под Ubuntu 16.04.

Данные файлы реализуют идею клонирования исходного кода внутрь контейнера.

Запускается вся сборка с помощью Makefile. Он очень короткий и содержит достаточно комментариев. Его основа — это создание образа и запуск контейнера:

В этом этапе сборки создается образ контейнера с именем, состоящим из префикса simple-qt- и названия системы (для centos 7 это будет simple-qt-centos7). В качестве Dockerfile используется соответствующий файл с разрешением .docker. Далее запускается контейнер на основе созданного образа, и к нему монтируется папка для копирования артефактов сборки.

После запуска команды в директории docker, в папке docker/releases будут находится результаты сборки под несколько платформ.

Таким образом наша инфраструктура для сборки SimpleQtProject будет выглядеть следующим образом:

Достоинства данной конфигурации:

  1. Локальность. Разработчик собирает проект для нескольких платформ на своей локальной машине, это исключает необходимость содержать парк серверов, настраивать копирование артефактов между серверами по сети, отправку и обработку сетевых команд.
  2. Изоляция окружения. Контейнер обеспечивает полностью изолированную среду для сборки конкретного приложения. Есть возможность обеспечить сборку проектов с несовместимыми окружениями на одной машине (например таких, которые требуют различных версий одной и той же библиотеки).
  3. Версионирование. Поместив Dockerfile в git-репозиторий, можно отслеживать изменения в среде сборки с выходом новых релизов, откатываться к предыдущим версиям среды сборки и пр.
  4. Мобильность. При необходимости данная инфраструктура без особых проблем разворачивается на другом компьютере. Технология создания позволяет вносить изменения в сам образ очень легко — достаточно обновить Dockerfile и запустить сборку образа.
  5. Самодокументируемость. По сути, Dockerfile содержит шаги для развертывания окружения сборки. Поэтому, при необходимости развернуть такое окружение, но уже в обычной системе, можно воспользоваться командами из него же.
  6. Легковесность. Контейнер запускается в момент начала сборки и останавливается по ее завершению автоматически. Он не тратит процессорное время и оперативную память впустую.

Однако есть и существенный минус — сборка проекта потребует и сборки образа контейнера. При первом запуске это может занять продолжительное время. Но при повторных, особенно если Dockerfile не менялся, образ собирается с использованием кеша в разы быстрее.

Так же необходимо не забывать очищать остановленные контейнеры.

Step 2: Customize and Push to Docker Hub

The last step used a Docker image which Microsoft publishes and maintains. Next step, create your own custom image. You should have a Docker ID, you probably created it to download Docker Desktop.

In your favorite text editor create a file called Dockerfile in the same C:\temp directory. No extension, just Dockerfile. Paste in this code and save the file:

This tells Docker to use the same IIS base image, and create a layer that adds in the HTML you created in the last step. Instead of manually copying a file into the container, you will create an image with your HTML already inside it. To build the image, in your terminal, type:

Two things, first replace <YourDockerID> with your Docker ID. Also notice the “.” at the end of the line. That tells Docker to build in the context of this directory. So when it looks to COPY the file to /inetpub/wwwroot it will use the file from this directory.

You can run it:

And go to http://localhost:8081 to see the page — note your original container is still running and you can see it at http://localhost:8080.

Finally push to Docker Hub:

You may be asked to login if you haven’t already. Then you can go to hub.docker.com, login and check your repositories

Finally, stop and remove the running containers:

Step 3: Run a Multi-Service App

Easily connect multiple services together

Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. Docker Compose installs automatically with Docker Desktop.

A multi-container app is an app that has multiple containers running and communicating with each other. This sample uses a simple .Net Core web app running with a MySQL database. You can check out the app in our dockersamples GitHub repo. We’ve pushed two images to the Docker Hub under the dockersamples repo. Docker Compose handles service discovery directly, allowing the app to reference the service directly and Docker will route traffic to the right container. To try it out, open a text editor and paste the text from this file. Then save it as docker-compose.yml.

There’s a lot of details in there but basically you can see that it specifies the images to be used, the service names, application configuration, the ports available, and networks the different services are on.

To run it, open a command line and navigate to the same directory as the docker-compose.yml file. At the command line, type

You will see a bunch of commands go by as it pulls images from Docker Hub and then starts them up. When it has finished running, navigate to http://localhost. You should see a music album viewer. The .NET Core application saves data in the MySQL database — you don’t need .NET Core or MySQL installed, all the components are running in Docker.

To stop and remove all services and resources created by Docker Compose:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector