Рубрики
Без рубрики

Docker Handbook – 2021 издание

Концепция сама контейнеризации довольно старая. Но появление двигателя Docker в 2013 году сделало намного проще консистерировать ваши приложения. Согласно опросу разработчиков переполнения стека – 2020, Docker – это самая желанная платформа № 1, # 2 самая любимая платформа, а также # 3

Автор оригинала: FreeCodeCamp Community Member.

Концепция сама контейнеризации довольно старая. Но появление Docker Engine В 2013 году намного проще консистерировать ваши приложения.

Согласно Обзор разработчика переполнения стека – 2020 , Докер это # 1 Самая разная платформа , # 2 самая любимая платформа , а также # 3 самая популярная платформа Отказ

Как это может быть востребовано, начать работу может показаться немного запугиваться. Таким образом, в этой книге мы будем изучать все от основ до более промежуточного уровня контейнера. После прохождения всей книги вы должны быть в состоянии:

  • Контейнеризация (почти) любое приложение
  • Загрузите пользовательские изображения Docker в онлайн-реестры
  • Работа с несколькими контейнерами, используя Docker Compose

Предпосылки

  • Знакомство с терминалом Linux
  • Знакомство с JavaScript (некоторые более поздние проекты используют JavaScript)

Оглавление

  • Введение в контейнеризацию и докер
  • Как установить Docker
    • Как установить Docker на MacOS
    • Как установить Docker на Windows
    • Как установить Docker на Linux
  • Здравствуйте, World в Docker – Intro в основы докера
    • Что такое контейнер?
    • Что такое документ докера?
    • Что такое Docker Registry?
    • Обзор архитектуры докера
    • Полная картина
  • Основы манипулирования контейнера Docker
    • Как запустить контейнер
    • Как опубликовать порт
    • Как использовать отдельный режим
    • Как перечислить контейнеры
    • Как назвать или переименовать контейнер
    • Как остановить или убить беговой контейнер
    • Как перезапустить контейнер
    • Как создать контейнер без бега
    • Как удалить свисающие контейнеры
    • Как запустить контейнер в интерактивном режиме
    • Как выполнить команды внутри контейнера
    • Как работать с исполняемыми изображениями
  • Основы манипулирования изображения докера
    • Как создать образа докера
    • Как поместить документы Docker
    • Как перечислить и удалить образы докера
    • Как понять много слоев докера
    • Как построить Nginx из источника
    • Как оптимизировать образы докера
    • Обнимая альпийский Linux
    • Как создать исполняемые изображения Docker
    • Как поделиться своими изображениями Docker онлайн
  • Как контейнеризировать приложение JavaScript
    • Как написать Development DockerFile
    • Как работать с креплениями Bind в Docker
    • Как работать с анонимными томами в докере
    • Как выполнить многоядерные сборки в Docker
    • Как игнорировать ненужные файлы
  • Основы манипулирования сетью в докере
    • Основы Docker Network
    • Как создать пользовательский мост в Docker
    • Как прикрепить контейнер к сети в Docker
    • Как отсоединить контейнеры из сети в докере
    • Как избавиться от сетей в Docker
  • Как контейнеризировать многофункциональное приложение JavaScript
    • Как запустить сервер базы данных
    • Как работать с названными томами в докере
    • Как получить доступ к журналам из контейнера в Docker
    • Как создать сеть и прикрепление сервера базы данных в Docker
    • Как написать DockerFile
    • Как выполнить команды в запущенном контейнере
    • Как написать сценарии управления в Docker
  • Как составить проекты, используя docker-compose
    • Docker Compose Основы
    • Как начать сервисы в Docker Compose
    • Как перечислить услуги в Docker Compose
    • Как выполнить команды внутри беговой службы в Docker Compose
    • Как получить доступ к журналам из беговой службы в Docker Compose
    • Как остановить услуги в Docker Compose
    • Как составить приложение полнотека в Docker Compose
  • Заключение

Код проекта

Код для примеров проектов можно найти в следующем репозитории:

Вы можете найти полный код в Завершено ветка.

Взносы

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

Я обычно делаю свои изменения и обновляю на версию Gitbook в книге, а затем опубликуете их на FreeCodeCamp. Вы можете найти всегда обновленную и часто нестабильную версию книги по следующей ссылке:

Если вы ищете замороженную, но стабильную версию книги, то FreeCodeCamp будет лучшее место для поезда:

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

Введение в контейнеризацию и докер

По словам IBM ,

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

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

Если вы сделаете список зависимостей, этот список может выглядеть следующим образом:

  • Node.js.
  • Express.js.
  • SQLite3.

Ну, теоретически это должно быть это. Но практически есть и другие вещи. Оказывается Node.js использует инструмент сборки, известный как Узел-GYP Для строительства нативных дополнений. И согласно Инструкция по установке В Официальный репозиторий Этот инструмент сборки требует Python 2 или 3 и соответствующую цепочку инструментов компилятора C/C ++.

Принимая все это во внимание, окончательный список зависимостей заключается в следующем:

  • Node.js.
  • Express.js.
  • SQLite3.
  • Python 2 или 3
  • C/C ++ цепь инструментов

Установка Python 2 или 3 довольно прост, независимо от платформы, которую вы включенные. Настройка цепочки инструментов C/C ++ довольно проста в Linux, но на Windows и Mac это болезненная задача.

В Windows The C ++ Build Tools Package меры в гигабайтах и занимают довольно много времени для установки. На Mac вы можете либо установить гигантский Xcode Применение или намного меньше Инструменты командной строки для Xcode упаковка.

Независимо от того, что вы устанавливаете, он все же может нарушить обновления ОС. На самом деле проблема настолько распространена, что есть Установка заметки для MacOS Catalina Доступно на официальном хранилище.

Предположим, что вы проходили через все хлопоты на создание зависимостей и начали работать над проектом. Это значит, что вы не опасны сейчас? Конечно нет.

Что, если у вас есть товарищ по команде, который использует Windows, пока вы используете Linux. Теперь вы должны рассмотреть несоответствия того, как эти две разные операционные системы обрабатывают пути. Или тот факт, что популярные технологии, такие как nginx не очень хорошо оптимизированы для работы в Windows. Некоторые технологии, такие как Redis Даже не приходите предварительно построенные для Windows.

Даже если вы проходите по всей фазе разработки, что если лицо, ответственное за управление серверами, следует неправильному процедуру развертывания?

Все эти проблемы могут быть решены, если только вы могли бы как-то:

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

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

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

Сейчас вопрос: «Какую роль играет здесь?»

Как я уже объяснил, контейнеризация – это идея, которая решает множество проблем в разработке программного обеспечения, положив вещи в коробки.

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

Теперь Docker – это не единственный инструмент для контейнеров на рынке, это просто самый популярный. Другой двигатель контейнеразации, который я люблю, называется Подман Разработан красной шляпой. Другие инструменты, такие как Канико Google, RKT Кровару удивительно, но они еще не готовы быть заправленной заменой для докера.

Кроме того, если вы хотите урок истории, вы можете прочитать удивительную Краткая история контейнеров: с 1970-х годов до сих пор который охватывает большую часть основных токарных точек для технологии.

Как установить Docker

Установка Docker сильно варьируется в зависимости от операционной системы, которую вы используете. Но это универсально просто через доску.

Докер безупречно работает на всех трех основных платформах, Mac, Windows и Linux. Среди трех процесс установки на Mac является самым простым, поэтому мы начнем там.

Как установить Docker на MacOS

На Mac все, что вам нужно сделать, это перейти к официальному Скачать страницу и нажмите на Скачать для Mac (стабильный) кнопка.

Вы получите регулярный вид Image Disk Apple Файл и внутри файла будет приложение. Все, что вам нужно сделать, это перетащить файл и бросить его в каталог приложений.

Вы можете начать Docker, просто дважды щелкнув значок приложения. Как только приложение запускается, вы увидите, что значок Docker появится в вашем меню-баре.

Теперь откройте терминал и выполните Docker --version и Docker-Compose --version обеспечить успех установки.

Как установить Docker на Windows

В Windows процедура практически то же самое, за исключением нескольких дополнительных шагов, которые вам нужно будет пройти. Шаги установки следующие:

  1. Перейдите к Этот сайт И следуйте инструкциям для установки WSL2 на Windows 10.
  2. Затем перейдите к официальному Скачать страницу и нажмите на Загрузить для Windows (стабильный) кнопка.
  3. Дважды щелкните загруженный установщик и пройдите по установке по умолчанию.

Как только установка будет сделана, начните Docker Desktop либо из меню «Пуск» или «Ваш рабочий стол». Значок докера должен отображаться на вашей панели задач.

Теперь откройте Ubuntu или любой расстройт, который вы установили из Microsoft Store. Выполнить Docker --version и Docker-Compose --version Команды, чтобы убедиться, что установка была успешной.

Вы можете получить доступ к Docker из вашей обычной командной строки или PowerShell. Просто я предпочитаю использовать WSL2 над любой другой командной строкой в Windows.

Как установить Docker на Linux

Установка Docker на Linux – это немного другого процесса, и в зависимости от распределения, который вы включены, он может варьироваться еще больше. Но если честно, установка так же легкая (если не проще) как две другие платформы.

Пакет Docker Desktop на Windows или Mac – это коллекция инструментов, таких как Docker Engine , Docker Compose , Docker Dashboard , Кубернаны И несколько других вкусностей.

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

Как только установка будет сделана, откройте терминал и выполните Docker --version и Docker-Compose --version обеспечить успех установки.

Хотя Docker выполняет довольно хорошо, независимо от платформы, которую вы включенные, я предпочитаю Linux над другими. На протяжении всей книги я буду переключаться между моим Ubuntu 20.10 и Федора 33 рабочие станции.

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

Я знаю о хороших инструментах GUI, доступных для разных платформ, но изучение команд Common Docker является одним из основных целей этой книги.

Здравствуйте, World в Docker – Intro в основы докера

Теперь, когда у вас есть докер и работает на вашу машину, пришло время запускать свой первый контейнер. Откройте терминал и запустите следующую команду:

docker run hello-world

# Unable to find image 'hello-world:latest' locally
# latest: Pulling from library/hello-world
# 0e03bdcc26d7: Pull complete 
# Digest: sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc
# Status: Downloaded newer image for hello-world:latest
# 
# Hello from Docker!
# This message shows that your installation appears to be working correctly.
# 
# To generate this message, Docker took the following steps:
#  1. The Docker client contacted the Docker daemon.
#  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
#     (amd64)
#  3. The Docker daemon created a new container from that image which runs the
#     executable that produces the output you are currently reading.
#  4. The Docker daemon streamed that output to the Docker client, which sent it
#     to your terminal.
#
# To try something more ambitious, you can run an Ubuntu container with:
#  $ docker run -it ubuntu bash
# 
# Share images, automate workflows, and more with a free Docker ID:
#  https://hub.docker.com/
#
# For more examples and ideas, visit:
#  https://docs.docker.com/get-started/

Привет-мир Изображение представляет собой пример минимальной контейнеризации с докером. У него есть одна программа, собранная из hello.c Файл, ответственный за печать сообщения, которое вы видите на вашем терминале.

Теперь в вашем терминале вы можете использовать Docker PS-A Команда, чтобы посмотреть на все контейнеры, которые в данный момент работают или запускаются в прошлом:

docker ps -a

# CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
# 128ec8ceab71        hello-world         "/hello"            14 seconds ago      Exited (0) 13 seconds ago                      exciting_chebyshev

На выходе контейнер с именем Exciting_chebyshev был запущен с идентификатором контейнера 128ec8ceab71 используя Привет-мир изображение. Это имеет Выходу (0) 13 секунд назад где . (0) Выходной код означает, что во время выполнения контейнера не было создано ошибка.

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

  • Контейнер
  • Изображение
  • Реестр

Я перечислил три концепции в алфавитном порядке и начнут мои объяснения с первым в списке.

Что такое контейнер?

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

Официальный докер Ресурсы сайт говорит –

Вы можете рассмотреть контейнеры, чтобы быть следующим поколением виртуальных машин.

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

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

Виртуальные машины обычно создаются и управляются программой, известной как гипервизор, как Oracle VM VirtualBox , VMware WorkStation , КВМ , Microsoft Hyper-V и так далее. Эта программа Hypervisor обычно находится между хост-операционной системой и виртуальными машинами для выступления в качестве средства связи.

Каждая виртуальная машина поставляется с собственной гостевой операционной системой, которая так же тяжелая, как операционная система хоста.

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

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

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

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

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

В качестве демонстрации точки посмотрите на следующий код код:

uname -a
# Linux alpha-centauri 5.8.0-22-generic #23-Ubuntu SMP Fri Oct 9 00:34:40 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

docker run alpine uname -a
# Linux f08dbbe9199b 5.8.0-22-generic #23-Ubuntu SMP Fri Oct 9 00:34:40 UTC 2020 x86_64 Linux

В блоке кода выше я выполнил uname -a Команда на моей операционной системе Host, чтобы распечатать детали ядра. Затем на следующей строке я выполнил одну и ту же команду внутри контейнера, работающего Alpine Linux Отказ

Как вы можете видеть на выходе, контейнер действительно использует ядро из моей операционной системы Host. Это идет, чтобы доказать точку, которая контейнеры виртуализируют операционную систему хоста вместо собственной операционной системы.

Если вы на машине Windows, вы узнаете, что все контейнеры используют ядро WSL2. Это происходит потому, что WSL2 действует как задняя часть для докера на Windows. На MacOS Back-End по умолчанию является VM, работающим на Гиперкит гипервизор.

Что такое документ докера?

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

В прошлом разные контейнерные двигатели имели разные форматы изображения. Но позже, Открытая контейнерная инициатива (OCI) Определяется стандартной спецификацией для контейнерных изображений, которые выполняются основными двигателями контейнеризации. Это означает, что изображение, построенное с Docker, может использоваться с другим временем выполнения, такими как Podman без каких-либо дополнительных хлопот.

Контейнеры – это просто изображения в работе. Когда вы получаете изображение из Интернета и запустите контейнер, используя это изображение, вы по существу, создаете еще один временный писательский слой сверху предыдущих только для чтения.

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

Что такое Docker Registry?

Вы уже узнали о двух очень важных кусках головоломки, Контейнеры и Изображения Отказ Последний кусок является Реестр Отказ

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

На протяжении всей этой книги я буду использовать Docker Hub как мой реестр выбора.

Вы можете поделиться любым количеством публичных изображений на Docker Hub бесплатно. Люди по всему миру смогут загрузить их и использовать их свободно. Изображения, которые я загрузил, доступны в моем профиле ( Fhsinchy ).

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

Обзор архитектуры докера

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

Двигатель состоит из трех основных компонентов:

  1. Docker Daemon: Демон ( Dockerd ) – это процесс, который продолжает работать в фоновом режиме и ждет команд от клиента. Демон способен управлять различными объектами докера.
  2. Докерный клиент: Клиент ( Docker ) – это программа командной строки, в основном несет ответственность за транспортирующие команды, выданные пользователями.
  3. REST API: Остальные API действуют как мост между демоном и клиентом. Любая команда, выданная с помощью клиента, проходит через API, чтобы наконец достичь демона.

Согласно официальному Документы ,

Вы, как пользователь, обычно выполняют команды с помощью клиентского компонента. Затем клиент использует API для отдыха, чтобы добраться до долгое управление демон и выполнить свою работу.

Полная картина

Хорошо, достаточно говорить. Теперь пришло время понять, как все эти части головоломки вы только что узнали о работе в гармонии. Прежде чем я погрузился в объяснение того, что действительно происходит, когда вы управляете Докер бегите Hello-World Команда, позвольте мне показать вам небольшую диаграмму, которую я сделал:

Это изображение – слегка модифицированная версия, которую можно найти в официальном Документы Отказ События, которые возникают при выполнении команды, следующие:

  1. Вы выполняете Докер бегите Hello-World Команда, где Привет-мир это имя изображения.
  2. Докерный клиент достигает демона, говорит ему, чтобы получить Привет-мир изображение и запустить контейнер от этого.
  3. Docker Daemon смотрит на изображение в местном хранилище и понимает, что он там нет, в результате чего Невозможно найти изображение «Hello-World: последние» локально Это напечатано на вашем терминале.
  4. Затем демон достигает публичного реестра по умолчанию, который является Docker Hub и тянет в последней копии Привет-мир Изображение, указанное Последнее: вытягивание из библиотеки/Hello-World линия в вашем терминале.
  5. Docker Daemon затем создает новый контейнер из свежего изображения.
  6. Наконец, Docker Daemon запускает контейнер, созданный с помощью Привет-мир Изображение выводит стену текста на вашем терминале.

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

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9
Status: Downloaded newer image for hello-world:latest

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

Основы манипулирования контейнера Docker

В предыдущих разделах вы узнали о строительных блоках Docker и также запустили контейнер, используя Docker Run команда.

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

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

Как запустить контейнер

Ранее вы использовали Docker Run Чтобы создать и запустить контейнер, используя Привет-мир изображение. Общий синтаксис для этой команды выглядит следующим образом:

docker run 

Хотя это совершенно допустимая команда, есть лучший способ диспетчеризации команд Докер демон

До версии 1.13 У докера был только ранее упомянутый командный синтаксис. Позже командная строка была реструктурированный иметь следующий синтаксис:

docker   

В этом синтаксисе:

  • объект Указывает тип объекта Docker, который вы будете манипулировать. Это может быть Контейнер , изображение , сеть или Том объект.
  • команда Указывает, что задача выполняется демоном, то есть Беги команда.
  • Варианты Может быть любой допустимый параметр, который может переопределить поведение по умолчанию команду, как --publish Вариант для отображения порта.

Теперь, следуя этому синтаксису Беги Команда может быть написана следующим образом:

docker container run 

Имя изображения Может быть любого изображения из онлайн-реестра или вашей локальной системы. В качестве примера вы можете попробовать запустить контейнер, используя FHSINCHY/HELLO-DOCK изображение. Это изображение содержит простой Vue.js Приложение, которое работает на порту 80 внутри контейнера.

Чтобы запустить контейнер, используя это изображение, выполните следующую команду на вашем терминале:

docker container run --publish 8080:80 fhsinchy/hello-dock

# /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
# /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
# /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
# 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
# 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
# /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
# /docker-entrypoint.sh: Configuration complete; ready for start up

Команда довольно объяснительная. Единственная часть, которая может потребовать некоторого объяснения, это --publish 8080: 80 Часть, которая будет объяснена в следующем подразделе.

Как опубликовать порт

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

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

--publish :

Когда вы написали --publish 8080: 80 В предыдущем подразделе это означало, что любой запрос, отправленный в порт 8080 вашей хост-системы, будет перенаправлен в порт 80 внутри контейнера.

Теперь, чтобы получить доступ к приложению в вашем браузере, посетите http://127.0.0.1:8080 Отказ

Вы можете остановить контейнер, просто нажав Ctrl + C Комбинация ключей во время окна терминала полностью полностью закрывается или закрывает окно терминала.

Как использовать отдельный режим

Еще один очень популярный вариант Беги Команда – это --detach или -d вариант. В приведенном выше примере, чтобы контейнер продолжать работать, вам пришлось открыть окно терминала. Закрытие окна терминала также остановило бегунного контейнера.

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

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

docker container run --detach --publish 8080:80 fhsinchy/hello-dock

# 9f21cb77705810797c4b847dbd330d9c732ffddba14fb435470567a7a3f46cdc

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

Порядок вариантов, которые вы предоставляете, не имеет значения. Если вы поместите --publish вариант до --detach Вариант, это будет работать точно так же. Одна вещь, которую вы должны иметь в виду в случае Беги Команда заключается в том, что имя изображения должно прийти последнее. Если вы положите что-либо после названия изображения, то это будет передано в качестве аргумента в точку входа контейнера (объяснено в командах для выполнения внутри контейнера подсечка) и может привести к неожиданным ситуациям.

Как перечислить контейнеры

Контейнер Ls . Команда может быть использована для перечисления контейнеров, которые в данный момент работает. Для этого выполнить следующую команду:

docker container ls

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                  NAMES
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   5 seconds ago       Up 5 seconds        0.0.0.0:8080->80/tcp   gifted_sammet

Контейнер с именем Gifted_sammet это работает. Это было создано 5 секунд назад и статус это До 5 секунд, что указывает на то, что контейнер работает нормально с момента его создания.

Контейнер ID это 9F21CB777058 Какие из первых 12 символов полного идентификатора контейнера. Полный контейнер ID 9F21CB77705810797C4B847DBD330D9C732FFDDBA14FB435470567A7A3F46CDC который длиной 64 символа. Этот полный идентификатор контейнера был напечатан как выход Docker Container Run команда в предыдущем разделе.

Перечислены под Порты Столбец, порт 8080 из вашей локальной сети указывает на порт 80 внутри контейнера. Имя Gifted_sammet генерируется докером и может быть что-то совершенно другое на вашем компьютере.

Контейнер Ls . Команда только перечисляет контейнеры, которые в данный момент работают в вашей системе. Для того, чтобы перечислить контейнеры, которые запускаются в прошлом, вы можете использовать - Все или вариант.

docker container ls --all

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                     PORTS                  NAMES
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   2 minutes ago       Up 2 minutes               0.0.0.0:8080->80/tcp   gifted_sammet
# 6cf52771dde1        fhsinchy/hello-dock   "/docker-entrypoint.…"   3 minutes ago       Exited (0) 3 minutes ago                          reverent_torvalds
# 128ec8ceab71        hello-world           "/hello"                 4 minutes ago       Exited (0) 4 minutes ago                          exciting_chebyshev

Как вы можете видеть, второй контейнер в списке Reverent_torvalds Был создан ранее и вышел с кодом состояния 0, который указывает на то, что во время выполнения контейнера не было создано ошибка.

Как назвать или переименовать контейнер

По умолчанию каждый контейнер имеет два идентификатора. Они следующие:

  • Контейнер ID – Случайный 64 символ длиной символов.
  • Имя – Сочетание двух случайных слов, соединенных с подчеркиванием.

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

Наименование контейнера может быть достигнуто с помощью --Name вариант. Чтобы запустить другой контейнер, используя FHSINCHY/HELLO-DOCK Изображение с именем Привет-док-контейнер Вы можете выполнить следующую команду:

docker container run --detach --publish 8888:80 --name hello-dock-container fhsinchy/hello-dock

# b1db06e400c4c5e81a93a64d30acc1bf821bed63af36cab5cdb95d25e114f5fb

Порт 8080 в локальной сети занимает Gifted_sammet Контейнер (контейнер, созданный в предыдущем подразделе). Вот почему вам придется использовать другой номер порта, например, 8888. Теперь, чтобы проверить, запустить Контейнер Ls . команда:

docker container ls

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                  NAMES
# b1db06e400c4        fhsinchy/hello-dock   "/docker-entrypoint.…"   28 seconds ago      Up 26 seconds       0.0.0.0:8888->80/tcp   hello-dock-container
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   4 minutes ago       Up 4 minutes        0.0.0.0:8080->80/tcp   gifted_sammet

Новый контейнер с именем Привет-док-контейнер был начат.

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

docker container rename  

Переименовать Gifted_sammet Контейнер к Привет-док-контейнер-2 Выполните следующую команду:

docker container rename gifted_sammet hello-dock-container-2

Команда не дает никакой вывод, но вы можете убедиться, что изменения имели место с помощью Контейнер Ls . команда. Переименовать Команда работает для контейнеров как в запущенном состоянии, так и остановленное состояние.

Как остановить или убить беговой контейнер

Контейнеры, работающие на переднем плане, могут быть остановлены, просто закрывая окно терминала или нажав Ctrl + C Отказ Однако контейнеры, работающие на заднем плане, не могут быть остановлены таким же образом.

Есть две команды, которые имеют дело с этой задачей. Первый – это Контейнер Стоп команда. Общий синтаксис для команды выглядит следующим образом:

docker container stop 

Где Контейнер идентификатор Может быть либо идентификатор или имя контейнера.

Я надеюсь, что вы помните контейнер, который вы начали в предыдущем разделе. Это все еще работает на заднем плане. Получите идентификатор для этого контейнера, используя Докерный контейнер Ls (Я буду использовать Привет-док-контейнер Контейнер для этой демонстрации). Теперь выполните следующую команду, чтобы остановить контейнер:

docker container stop hello-dock-container

# hello-dock-container

Если вы используете имя в качестве идентификатора, вы получите отброшенное имя в качестве вывода. Стоп Команда изящно отключает контейнер, отправив SIGTERM сигнал. Если контейнер не останавливается в течение определенного периода, а SIGKILL Отправляется сигнал, который немедленно отключает контейнер.

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

docker container kill hello-dock-container-2

# hello-dock-container-2

Как перезапустить контейнер

Когда я говорю, перезапустите, я имею в виду два сценария специально. Они следующие:

  • Перезапуск контейнера, который был ранее остановлен или убит.
  • Перезагрузка бегового контейнера.

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

docker container start 

Вы можете получить список всех контейнеров, выполнив Контейнер ls --all команда. Тогда ищите контейнеры с Выходил статус.

docker container ls --all

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                        PORTS               NAMES
# b1db06e400c4        fhsinchy/hello-dock   "/docker-entrypoint.…"   3 minutes ago       Exited (0) 47 seconds ago                         hello-dock-container
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   7 minutes ago       Exited (137) 17 seconds ago                       hello-dock-container-2
# 6cf52771dde1        fhsinchy/hello-dock   "/docker-entrypoint.…"   7 minutes ago       Exited (0) 7 minutes ago                          reverent_torvalds
# 128ec8ceab71        hello-world           "/hello"                 9 minutes ago       Exited (0) 9 minutes ago                          exciting_chebyshev

Теперь, чтобы перезапустить Привет-док-контейнер Контейнер, вы можете выполнить следующую команду:

docker container start hello-dock-container

# hello-dock-container

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

Старт контейнера Команда начнет любой контейнер в отдельночном режиме по умолчанию и сохраняет какие-либо конфигурации портов, сделанные ранее. Так что, если вы посетите http://127.0.0.1:8080 Теперь вы должны иметь возможность получить доступ к Привет-док Приложение просто как раньше.

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

docker container restart hello-dock-container-2

# hello-dock-container-2

Основное различие между двумя командами заключается в том, что Контейнер перезапускает Команда пытается остановить целевой контейнер, а затем снова запускает его резервное копирование, тогда как команда запуска просто запускает уже остановленную контейнер.

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

Как создать контейнер без бега

До сих пор в этом разделе вы начали контейнеры, используя Контейнер работает Команда, которая на самом деле является комбинацией двух отдельных команд. Эти команды следующие:

  • Контейнер создает Команда создает контейнер с данного изображения.
  • Старт контейнера Команда запускает контейнер, который был уже создан.

Теперь, чтобы выполнить демонстрацию, показанную в разделе «Беговые контейнеры», используя эти две команды, вы можете сделать что-то вроде следующего:

docker container create --publish 8080:80 fhsinchy/hello-dock

# 2e7ef5098bab92f4536eb9a372d9b99ed852a9a816c341127399f51a6d053856

docker container ls --all

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS               NAMES
# 2e7ef5098bab        fhsinchy/hello-dock   "/docker-entrypoint.…"   30 seconds ago      Created                                 hello-dock

Очевидно на выходе Контейнер ls --all Команда, контейнер с именем Привет-док был создан с помощью FHSINCHY/HELLO-DOCK изображение. Статус контейнера Создано На данный момент и, учитывая, что он не работает, он не будет перечислен без использования - Все вариант.

Как только контейнер создан, он может быть запущен с помощью Старт контейнера команда.

docker container start hello-dock

# hello-dock

docker container ls

# CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS                  NAMES
# 2e7ef5098bab        fhsinchy/hello-dock   "/docker-entrypoint.…"   About a minute ago   Up 29 seconds       0.0.0.0:8080->80/tcp   hello-dock

Контейнер Статус изменился с Создано к До 29 секунд что указывает на то, что контейнер сейчас находится в запущенном состоянии. Конфигурация порта также показана в Порты столбец, который был ранее пустым.

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

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

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

Для того, чтобы удалить остановленный контейнер, вы можете использовать Контейнер RM команда. Общий синтаксис выглядит следующим образом:

docker container rm 

Чтобы узнать, какие контейнеры не работают, используйте Контейнер ls --all Команда и искать контейнеры с Выходил статус.

docker container ls --all

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                      PORTS                  NAMES
# b1db06e400c4        fhsinchy/hello-dock   "/docker-entrypoint.…"   6 minutes ago       Up About a minute           0.0.0.0:8888->80/tcp   hello-dock-container
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   10 minutes ago      Up About a minute           0.0.0.0:8080->80/tcp   hello-dock-container-2
# 6cf52771dde1        fhsinchy/hello-dock   "/docker-entrypoint.…"   10 minutes ago      Exited (0) 10 minutes ago                          reverent_torvalds
# 128ec8ceab71        hello-world           "/hello"                 12 minutes ago      Exited (0) 12 minutes ago                          exciting_chebyshev

Как видно на выходе, контейнеры с ID 6CF52771DDE1 и 128ec8ceab71 не бегают. Удалить 6CF52771DDE1 Вы можете выполнить следующую команду:

docker container rm 6cf52771dde1

# 6cf52771dde1

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

Или вместо удаления отдельных контейнеров, если вы хотите удалить все висячие контейнеры, вы можете использовать Контейнер Brune команда.

Вы можете проверить список контейнеров, используя Контейнер ls --all Команда, чтобы убедиться, что висячие контейнеры были удалены:

docker container ls --all

# CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                  NAMES
# b1db06e400c4        fhsinchy/hello-dock   "/docker-entrypoint.…"   8 minutes ago       Up 3 minutes        0.0.0.0:8888->80/tcp   hello-dock-container
# 9f21cb777058        fhsinchy/hello-dock   "/docker-entrypoint.…"   12 minutes ago      Up 3 minutes        0.0.0.0:8080->80/tcp   hello-dock-container-2

Если вы следуете за книгу именно так, как написано до сих пор, вы должны увидеть только Привет-док-контейнер и Привет-док-контейнер-2 в списке. Я бы предложил остановить и удалить обе контейнеры, прежде чем перейти к следующему разделу.

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

docker container run --rm --detach --publish 8888:80 --name hello-dock-volatile fhsinchy/hello-dock

# 0d74e14091dc6262732bee226d95702c21894678efb4043663f7911c53fb79f3

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

docker container ls

# CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                  NAMES
# 0d74e14091dc   fhsinchy/hello-dock   "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:8888->80/tcp   hello-dock-volatile

Теперь, если вы остановите контейнер, а затем снова проверьте с Контейнер ls --all команда:

docker container stop hello-dock-volatile

# hello-dock-volatile

docker container ls --all

# CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Контейнер был удален автоматически. Отныне я буду использовать --rm вариант для большинства контейнеров. Я явно упомяну, где он не нужен.

Как запустить контейнер в интерактивном режиме

До сих пор у вас только контейнеры, созданные из-за Привет-мир изображение или FHSINCHY/HELLO-DOCK изображение. Эти изображения сделаны для выполнения простых программ, которые не интерактивны.

Ну, все изображения не так просто. Изображения могут инкапсулировать целое распространение Linux внутри них.

Популярные распределения, такие как Ubuntu , Федора и Debian Все имеют официальные документы докера, доступные в концентрате. Языки программирования, такие как Python , PHP , идти или время пробега, как Узел и Deno У всех есть свои официальные изображения.

Эти изображения не просто запускают некоторую предварительно настроенную программу. Это вместо этого настроено для запуска оболочки по умолчанию. В случае изображения операционной системы это может быть что-то вроде Sh или Bash И в случае языков программирования или время прохождения, это обычно их языковая оболочка по умолчанию.

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

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

docker container run --rm -it ubuntu

# root@dbb1f56b9563:/# cat /etc/os-release
# NAME="Ubuntu"
# VERSION="20.04.1 LTS (Focal Fossa)"
# ID=ubuntu
# ID_LIKE=debian
# PRETTY_NAME="Ubuntu 20.04.1 LTS"
# VERSION_ID="20.04"
# HOME_URL="https://www.ubuntu.com/"
# SUPPORT_URL="https://help.ubuntu.com/"
# BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
# PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
# VERSION_CODENAME=focal
# UBUNTU_CODENAME=focal

Как вы можете увидеть с вывода CAT/ETC/OS-RELEACE Команда, я действительно взаимодействую с Bash, бегающим внутри контейнера Ubuntu.

-итайте Опция Устанавливает сцену для вас, чтобы взаимодействовать с любой интерактивной программой внутри контейнера. Этот вариант на самом деле два отдельных параметра, пюреных вместе.

  • или - Интерактивность Опция подключает вас к входному потоку контейнера, чтобы вы могли отправлять входы в Bash.
  • -t или --Тти Опция гарантирует, что вы получите хорошее форматирование и нативный терминальный опыт, выделяя псевдо-TTY.

Вам нужно использовать -итайте Вариант всякий раз, когда вы хотите запустить контейнер в интерактивном режиме. Другой пример может работать Узел Изображение следующим образом:

docker container run -it node

# Welcome to Node.js v15.0.0.
# Type ".help" for more information.
# > ['farhan', 'hasin', 'chowdhury'].map(name => name.toUpperCase())
# [ 'FARHAN', 'HASIN', 'CHOWDHURY' ]

Любой действительный код JavaScript может быть выполнен в оболочке узла. Вместо письма -итайте Вы можете быть более Verbose, написав --interactive --tty в отдельности.

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

В Hello World in Docker раздел этой книги вы видели, как я выполнял команду внутри альпийского контейнера Linux. Это пошло что-то вроде этого:

docker run alpine uname -a
# Linux f08dbbe9199b 5.8.0-22-generic #23-Ubuntu SMP Fri Oct 9 00:34:40 UTC 2020 x86_64 Linux

В этой команде я выполнил uname -a Команда внутри альпийского контейнера Linux. Сценарии, как это (где все, что вы хотите сделать, это выполнить определенную команду внутри определенного контейнера) довольно распространена.

Предположим, что вы хотите кодировать строку с помощью Base64 программа. Это то, что доступно практически в любой операционной системе Linux или Unix (но не на Windows).

В этой ситуации вы можете быстро раскрутить контейнер с использованием изображений, таких как Bitebox И пусть это сделает работу.

Общий синтаксис для кодирования строки с использованием Base64 составляет:

echo -n my-secret | base64

# bXktc2VjcmV0

И общий синтаксис для передачи команды на контейнер, который не работает, выглядит следующим образом:

docker container run  

Чтобы выполнить кодировку Base64 с помощью изображения Bitebox, вы можете выполнить следующую команду:

docker container run --rm busybox echo -n my-secret | base64

# bXktc2VjcmV0

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

Точка входа похожа на шлюз к изображению. Большинство изображений, кроме исполняемых изображений (объясненные в Работа с исполняемыми изображениями Подборка) Используйте оболочку или Sh как точка входа по умолчанию. Таким образом, любая действительная команда Shell может быть передана им в качестве аргументов.

Как работать с исполняемыми изображениями

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

Взять, например, мой RMbyext проект. Это простой сценарий Python, способный рекурсивно удалять файлы данных расширений. Чтобы узнать больше о проекте, вы можете проверить репозиторий:

Если у вас установлен Git и Python, вы можете установить этот скрипт, выполнив следующую команду:

pip install git+https://github.com/fhsinchy/rmbyext.git#egg=rmbyext

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

rmbyext 

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

touch a.pdf b.pdf c.txt d.pdf e.txt

ls

# a.pdf  b.pdf  c.txt  d.pdf  e.txt

Удалить все PDF Файлы из этого каталога, вы можете выполнить следующую команду:

rmbyext pdf

# Removing: PDF
# b.pdf
# a.pdf
# d.pdf

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

FHSINCHY/RMBYEXT Изображение ведет себя аналогично. Это изображение содержит копию RMbyext Скрипт и настроен для запуска скрипта в каталоге /зона внутри контейнера.

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

Один из способов предоставить контейнер прямого доступа к вашей локальной файловой системе, используя Привязать крепления Отказ

BIND COUNT позволяет сформировать двустороннюю связывание данных между содержимым локальной файловой системой каталога (источника) и другого каталога внутри контейнера (пункт назначения). Таким образом, любые изменения в каталоге назначения вступит в силу в исходном каталоге и Vise Versa.

Давайте посмотрим на привязку крепление в действии. Чтобы удалить файлы, используя это изображение вместо самой программы, вы можете выполнить следующую команду:

docker container run --rm -v $(pwd):/zone fhsinchy/rmbyext pdf

# Removing: PDF
# b.pdf
# a.pdf
# d.pdf

Как вы уже догадались, увидев -v $ (pwd):/зона Часть в команде, -V или --volume Опция используется для создания крепления связывания для контейнера. Этот вариант может предпринять три поля, разделенные двоеточиями ( : ). Общий синтаксис для опции выглядит следующим образом:

--volume ::

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

Исходный каталог в моем случае это /home/fhsinchy/Zone Отказ Учитывая, что мой терминал открывается внутри каталога, $ (PWD) будет заменен на /home/fhsinchy/Zone который содержит ранее упомянутые .PDF и .txt файлы.

Вы можете узнать больше о Команда замена здесь если вы хотите.

--volume или -V Опция действительна для Контейнер работает а также Контейнер создает команды. Мы рассмотрим объемы более подробно в предстоящих разделах, так что не волнуйтесь, если вы не понимаете их здесь очень хорошо.

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

Так что в конце концов Контейнер Docker Run --RM -V $ (PWD):/ZONE FHSINCHY/RMBYEXT PDF Команда переводит на Rmbyext PDF внутри контейнера. Исполняемые изображения не являются частотыми в дикой природе, но могут быть очень полезны в определенных случаях.

Основы манипулирования изображения докера

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

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

Я бы предложил вам установить Визуальный студийный код с официальным Дочсерское расширение с рынка. Это значительно поможет вашему опыту развития.

Как создать образа докера

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

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

docker container run --rm --detach --name default-nginx --publish 8080:80 nginx

# b379ecd5b6b9ae27c144e4fa12bdc5d0635543666f75c14039eea8d5f38e3f56

docker container ls

# CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
# b379ecd5b6b9        nginx               "/docker-entrypoint.…"   8 seconds ago       Up 8 seconds        0.0.0.0:8080->80/tcp   default-nginx

Теперь, если вы посетите http://127.0.0.1:8080 В браузере вы увидите страницу отклика по умолчанию.

Это все хорошо и хорошо, но что, если вы хотите сделать пользовательское изображение Nginx, которое функционирует точно так же, как официальный, но это построено вами? Это совершенно действительный сценарий, если честно. На самом деле, давайте сделаем это.

Чтобы сделать пользовательское изображение Nginx, у вас должна быть четкая картина того, что будет окончательное состояние изображения. На мой взгляд, изображение должно быть следующим:

  • Изображение должно иметь предварительно установленное nginx, которое можно сделать с помощью менеджера пакета или может быть построен из источника.
  • Изображение должно запустить Nginx автоматически при запуске.

Это просто. Если вы клонировали репозиторию проекта, связанные в этой книге, идите в корне в проекте и ищите каталог с именем Custom-Nginx там.

Теперь создайте новый файл с именем Dockerfile внутри этого каталога. А Dockerfile Является ли сборник инструкций, которые когда-то обрабатываются демоном, приводит к изображению. Содержание для Dockerfile составляет:

FROM ubuntu:latest

EXPOSE 80

RUN apt-get update && \
    apt-get install nginx -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

CMD ["nginx", "-g", "daemon off;"]

Изображения представляют собой многослойные файлы и в этом файле, каждая строка (известная как инструкции), которые вы написали, создает слой для вашего изображения.

  • Каждый действительный Dockerfile начинается с От Инструкция. Эта инструкция устанавливает базовое изображение для вашего результирующего изображения. Установка Ubuntu: последние В качестве базового изображения здесь вы получаете все доброту Ubuntu, уже доступно на вашем пользовательском изображении, поэтому вы можете использовать такие вещи, как APT-Get Команда для удобной установки пакета.
  • Выставлять Инструкция используется для указания порта, который необходимо опубликовать. Использование этой инструкции не означает, что вам не понадобится --publish порт. Вам еще нужно использовать --publish опция явно. Это Выставлять Инструкция работает как документация для тех, кто пытается запустить контейнер, используя ваше изображение. У него также есть некоторые другие виды использования, которые я здесь не буду обсуждать.
  • Беги Инструкция в Dockerfile Выполняет команду внутри корпуса контейнера. APT-Get Update && apt-get install install nginx -y Команда проверяет обновленные версии пакета и устанавливает nginx. apt-get clean && rm -rf/var/lib/apt/liess/* Команда используется для очистки кэша пакета, потому что вы не хотите ни одного ненужного багажа на вашем изображении. Эти две команды простые вещи Ubuntu, ничего нравятся. Беги Инструкции здесь написаны в оболочка форма. Они также могут быть написаны в exec форма. Вы можете проконсультироваться с Официальная ссылка для дополнительной информации.
  • Наконец CMD Инструкция Устанавливает команду по умолчанию для вашего изображения. Эта инструкция написана в exec Форма здесь состоит из трех отдельных частей. Здесь nginx Относится к исполняемому NGINX. -G и демон от являются вариантами для Nginx. Запуск Nginx в качестве одного процесса внутри контейнеров считается наилучшей практикой, следовательно, использование этой опции. CMD Инструкция также может быть написана в оболочка форма. Вы можете проконсультироваться с Официальная ссылка для дополнительной информации.

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

docker image  

Чтобы создать изображение, используя Dockerfile Вы только что написали, откройте свой терминал внутри Custom-Nginx каталог и выполнить следующую команду:

docker image build .

# Sending build context to Docker daemon  3.584kB
# Step 1/4 : FROM ubuntu:latest
#  ---> d70eaf7277ea
# Step 2/4 : EXPOSE 80
#  ---> Running in 9eae86582ec7
# Removing intermediate container 9eae86582ec7
#  ---> 8235bd799a56
# Step 3/4 : RUN apt-get update &&     apt-get install nginx -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> Running in a44725cbb3fa
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container a44725cbb3fa
#  ---> 3066bd20292d
# Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in 4792e4691660
# Removing intermediate container 4792e4691660
#  ---> 3199372aa3fc
# Successfully built 3199372aa3fc

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

  • Docker Image Build это команда для создания изображения. Демон находит любой файл с именем Dockerfile в контексте.
  • Отказ В конце устанавливает контекст для этой сборки. Контекст означает каталог, доступный на демон во время процесса сборки.

Теперь, чтобы запустить контейнер, используя это изображение, вы можете использовать Контейнер работает Команда в сочетании с идентификатором изображения, который вы получили в результате процесса сборки. В моем случае удостоверение личности 3199372AA3FC Очевидно, что Успешно построен 3199372AA3FC строка в предыдущем блоке кода.

docker container run --rm --detach --name custom-nginx-packaged --publish 8080:80 3199372aa3fc

# ec09d4e1f70c903c3b954c8d7958421cdd1ae3d079b57f929e44131fbf8069a0

docker container ls

# CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
# ec09d4e1f70c        3199372aa3fc        "nginx -g 'daemon of…"   23 seconds ago      Up 22 seconds       0.0.0.0:8080->80/tcp   custom-nginx-packaged

Чтобы проверить, посетить http://127.0.0.1:8080 И вы должны увидеть страницу отклика по умолчанию.

Как поместить документы Docker

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

Общий синтаксис для опции выглядит следующим образом:

--tag :

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

Возьми официальный MySQL Изображение, например. Если вы хотите запустить контейнер, используя определенную версию MySQL, например, 5,7, вы можете выполнить Контейнер Docker Run MySQL: 5.7 где MySQL это репозиторий изображения и 5.7 это тег.

Для того, чтобы пометить свой пользовательский образ Nginx с Custom-Nginx: упаковано Вы можете выполнить следующую команду:

docker image build --tag custom-nginx:packaged .

# Sending build context to Docker daemon  1.055MB
# Step 1/4 : FROM ubuntu:latest
#  ---> f63181f19b2f
# Step 2/4 : EXPOSE 80
#  ---> Running in 53ab370b9efc
# Removing intermediate container 53ab370b9efc
#  ---> 6d6460a74447
# Step 3/4 : RUN apt-get update &&     apt-get install nginx -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> Running in b4951b6b48bb
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container b4951b6b48bb
#  ---> fdc6cdd8925a
# Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in 3bdbd2af4f0e
# Removing intermediate container 3bdbd2af4f0e
#  ---> f8837621b99d
# Successfully built f8837621b99d
# Successfully tagged custom-nginx:packaged

Ничто не изменится, кроме того, что теперь вы можете ссылаться на ваше изображение как Custom-Nginx: упаковано вместо некоторой длинной случайной строки.

В тех случаях, когда вы забыли пометить изображение во время сборки, или, возможно, вы хотите изменить тег, вы можете использовать Тег изображения Команда сделать это:

docker image tag  :

## or ##

docker image tag : :

Как перечислить и удалить образы докера

Так же, как Контейнер Ls . Команда, вы можете использовать Изображение ls Команда для перечисления всех изображений в вашей локальной системе:

docker image ls

# REPOSITORY     TAG        IMAGE ID       CREATED         SIZE
#               3199372aa3fc   7 seconds ago   132MB
# custom-nginx   packaged   f8837621b99d   4 minutes ago   132MB

Перечисленные здесь изображения могут быть удалены, используя Image RM команда. Общий синтаксис выглядит следующим образом:

docker image rm 

Идентификатор может быть идентификатор изображения или репозиторий изображения. Если вы используете репозиторий, вам придется идентифицировать тег также. Чтобы удалить Custom-Nginx: упаковано Изображение, вы можете выполнить следующую команду:

docker image rm custom-nginx:packaged

# Untagged: custom-nginx:packaged
# Deleted: sha256:f8837621b99d3388a9e78d9ce49fbb773017f770eea80470fb85e0052beae242
# Deleted: sha256:fdc6cdd8925ac25b9e0ed1c8539f96ad89ba1b21793d061e2349b62dd517dadf
# Deleted: sha256:c20e4aa46615fe512a4133089a5cd66f9b7da76366c96548790d5bf865bd49c4
# Deleted: sha256:6d6460a744475a357a2b631a4098aa1862d04510f3625feb316358536fcd8641

Вы также можете использовать Image Brune Команда для очистки всех не помеченных висных изображений следующим образом:

docker image prune --force

# Deleted Images:
# deleted: sha256:ba9558bdf2beda81b9acc652ce4931a85f0fc7f69dbc91b4efc4561ef7378aff
# deleted: sha256:ad9cc3ff27f0d192f8fa5fadebf813537e02e6ad472f6536847c4de183c02c81
# deleted: sha256:f1e9b82068d43c1bb04ff3e4f0085b9f8903a12b27196df7f1145aa9296c85e7
# deleted: sha256:ec16024aa036172544908ec4e5f842627d04ef99ee9b8d9aaa26b9c2a4b52baa

# Total reclaimed space: 59.19MB

- Форс или -f Опция пропускает какие-либо вопросы подтверждения. Вы также можете использовать - Все или Возможность удалить все кэшированные изображения в вашем локальном реестре.

Как понять много слоев докера

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

Для этой демонстрации я буду использовать Custom-Nginx: упаковано Изображение из предыдущего подраздела.

Чтобы визуализировать многие слои изображения, вы можете использовать История изображений команда. Различные слои Custom-Nginx: упаковано Изображение может быть визуализировано следующим образом:

docker image history custom-nginx:packaged

# IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
# 7f16387f7307        5 minutes ago       /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B                             
# 587c805fe8df        5 minutes ago       /bin/sh -c apt-get update &&     apt-get ins…   60MB                
# 6fe4e51e35c1        6 minutes ago       /bin/sh -c #(nop)  EXPOSE 80                    0B                  
# d70eaf7277ea        17 hours ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
#            17 hours ago        /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B                  
#            17 hours ago        /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B                  
#            17 hours ago        /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   811B                
#            17 hours ago        /bin/sh -c #(nop) ADD file:435d9776fdd3a1834…   72.9MB

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

Теперь давайте посмотрим на изображения, начиная с изображения d70af7277ea до 7f16387f7307 Отказ Я буду игнорировать нижние четыре слоя, где Изображение это <Отсутствует> Как они не имеют нашей заботы.

  • d70af7277ea был создан /bin/sh -c # (nop) cmd ["/bin/bash"] Что указывает на то, что оболочка по умолчанию внутри Ubuntu была успешно загружена.
  • 6FE4E51E35C1 был создан /bin/sh -c # (nop) выставляют 80 Какое было второе инструкция в вашем коде.
  • 587C805FE8DF был создан /bin/sh -c apt-get update update && apt-get install nginx -y && apt-get clean && rm -rf/var/lib/apt/liess/* который был третьим инструкцией в вашем коде. Вы также можете увидеть, что это изображение имеет размер 60 МБ Учитывая все необходимые пакеты были установлены во время выполнения этой инструкции.
  • Наконец верхний самый слой 7f16387f7307 был создан /bin/sh -c # (nop) cmd ["nginx", "-G", "демон выключен;"] которые устанавливают команду по умолчанию для этого изображения.

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

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

Используя эту концепцию, Docker может избежать дублирования данных и может использовать ранее созданные слои в качестве кеша для более поздних сборки. Это приводит к компактным, эффективным изображениям, которые можно использовать везде.

Как построить Nginx из источника

В предыдущем подразделе вы узнали о От , Выставлять , Беги и CMD инструкции. В этом подсечении вы будете учиться намного больше о других инструкциях.

В этом подразделе вы снова создадите пользовательские изображения Nginx. Но поворот заключается в том, что вы будете строить Nginx от источника вместо того, чтобы установить его, используя некоторые пакетные менеджер, такие как APT-Get как в предыдущем примере.

Чтобы построить NGINX из источника, вам сначала нужен источник Nginx. Если вы квалифицировали мою репозиторию проектов, вы увидите файл с именем nginx-1.19.2.tar.gz внутри Custom-Nginx каталог. Вы будете использовать этот архив как источник для строительства Nginx.

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

  • Получите хороший базовый образ для построения приложения, как Ubuntu Отказ
  • Установите необходимые зависимости сборки на базовом изображении.
  • Скопируйте nginx-1.19.2.tar.gz Файл внутри изображения.
  • Извлечь содержимое архива и избавиться от него.
  • Настройте сборку, компилируйте и установите программу, используя сделать инструмент.
  • Избавьтесь от извлеченного исходного кода.
  • Беги nginx исполняемый.

Теперь, когда у вас есть план, давайте начнем с открытия старого Dockerfile и обновление его содержимого следующим образом:

FROM ubuntu:latest

RUN apt-get update && \
    apt-get install build-essential\ 
                    libpcre3 \
                    libpcre3-dev \
                    zlib1g \
                    zlib1g-dev \
                    libssl1.1 \
                    libssl-dev \
                    -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

COPY nginx-1.19.2.tar.gz .

RUN tar -xvf nginx-1.19.2.tar.gz && rm nginx-1.19.2.tar.gz

RUN cd nginx-1.19.2 && \
    ./configure \
        --sbin-path=/usr/bin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --http-log-path=/var/log/nginx/access.log \
        --with-pcre \
        --pid-path=/var/run/nginx.pid \
        --with-http_ssl_module && \
    make && make install

RUN rm -rf /nginx-1.19.2

CMD ["nginx", "-g", "daemon off;"]

Как видите, код внутри Dockerfile отражает семь шагов, о которых я говорил выше.

  • От Инструкции наборы Ubuntu в качестве базового изображения, делая идеальную среду для создания любого приложения.
  • Беги Инструкция устанавливает стандартные пакеты, необходимые для строительства Nginx от источника.
  • Скопировать Инструкция здесь – что-то новое. Эта инструкция несет ответственность за копирование nginx-1.19.2.tar.gz Файл внутри изображения. Общий синтаксис для Скопировать Инструкция – это Скопируйте <Пункт назначения> Где источник находится в вашей локальной файловой системе, и место назначения находится внутри вашего изображения. Отказ В качестве пункта назначения означает рабочий каталог внутри изображения, который по умолчанию / Если не установлено иначе.
  • Второй Беги Инструкция здесь извлекает содержимое из архива, используя Tar и избавляется от этого потом.
  • Файл архива содержит каталог под названием nginx-1.19.2 содержащий исходный код. Так на следующем шаге вам придется CD Внутри этого каталога и выполните процесс сборки. Вы можете прочитать Как установить программное обеспечение из исходного кода … и удалить его потом статья, чтобы узнать больше по теме.
  • После завершения сборки и установки вы удалите nginx-1.19.2 каталог, используя RM команда.
  • На заключительном шаге вы запускаете Nginx в одном режиме процесса, как вы делали раньше.

Теперь, чтобы создать изображение, используя этот код, выполните следующую команду:

docker image build --tag custom-nginx:built .

# Step 1/7 : FROM ubuntu:latest
#  ---> d70eaf7277ea
# Step 2/7 : RUN apt-get update &&     apt-get install build-essential                    libpcre3                     libpcre3-dev                     zlib1g                     zlib1g-dev                     libssl-dev                     -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> Running in 2d0aa912ea47
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container 2d0aa912ea47
#  ---> cbe1ced3da11
# Step 3/7 : COPY nginx-1.19.2.tar.gz .
#  ---> 7202902edf3f
# Step 4/7 : RUN tar -xvf nginx-1.19.2.tar.gz && rm nginx-1.19.2.tar.gz
 ---> Running in 4a4a95643020
### LONG EXTRACTION STUFF GOES HERE ###
# Removing intermediate container 4a4a95643020
#  ---> f9dec072d6d6
# Step 5/7 : RUN cd nginx-1.19.2 &&     ./configure         --sbin-path=/usr/bin/nginx         --conf-path=/etc/nginx/nginx.conf         --error-log-path=/var/log/nginx/error.log         --http-log-path=/var/log/nginx/access.log         --with-pcre         --pid-path=/var/run/nginx.pid         --with-http_ssl_module &&     make && make install
#  ---> Running in b07ba12f921e
### LONG CONFIGURATION AND BUILD STUFF GOES HERE ###
# Removing intermediate container b07ba12f921e
#  ---> 5a877edafd8b
# Step 6/7 : RUN rm -rf /nginx-1.19.2
#  ---> Running in 947e1d9ba828
# Removing intermediate container 947e1d9ba828
#  ---> a7702dc7abb7
# Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in 3110c7fdbd57
# Removing intermediate container 3110c7fdbd57
#  ---> eae55f7369d3
# Successfully built eae55f7369d3
# Successfully tagged custom-nginx:built

Этот код в порядке, но есть несколько мест, где мы можем сделать улучшения.

  • Вместо жесткого кодирования имени файла, как nginx-1.19.2.tar.gz , вы можете создать аргумент, используя Arg Инструкция. Таким образом, вы сможете изменить версию или имя файла, просто изменив аргумент.
  • Вместо того, чтобы загружать архив вручную, вы можете позволить демону загрузить файл во время процесса сборки. Есть еще одна команда, как Скопировать называется Добавить Инструкция, которая способна добавлять файлы из Интернета.

Откройте Dockerfile Файл и обновите его контент следующим образом:

FROM ubuntu:latest

RUN apt-get update && \
    apt-get install build-essential\ 
                    libpcre3 \
                    libpcre3-dev \
                    zlib1g \
                    zlib1g-dev \
                    libssl1.1 \
                    libssl-dev \
                    -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"

ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .

RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}

RUN cd ${FILENAME} && \
    ./configure \
        --sbin-path=/usr/bin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --http-log-path=/var/log/nginx/access.log \
        --with-pcre \
        --pid-path=/var/run/nginx.pid \
        --with-http_ssl_module && \
    make && make install

RUN rm -rf /${FILENAME}}

CMD ["nginx", "-g", "daemon off;"]

Код практически идентичен предыдущему блоке кода, за исключением новой инструкции, называемой Arg на линии 13, 14 и использование Добавить Инструкция по линии 16. Объяснение для обновленного кода выглядит следующим образом:

  • Arg Инструкция позволяет объявлять переменные, как на других языках. Эти переменные или аргументы могут быть доступны позже, используя использование $ {Имя аргумента} синтаксис. Здесь я поставил имя файла nginx-1.19.2 и расширение файла tar.gz в двух отдельных аргументах. Таким образом, я могу переключаться между новыми версиями Nginx или формата архива, сделав изменение всего в одном месте. В вышеуказанном коде я добавил значения по умолчанию для переменных. Изменные значения могут быть переданы как параметры Изображение построить команда также. Вы можете проконсультироваться с Официальная ссылка Больше подробностей.
  • В Добавить Инструкция, я сформировал URL-адрес загрузки, динамически используя аргументы, объявленные выше. https://nginx.org/download/$?ileName }.$ линия приведет к тому, что что-то вроде https://nginx.org/download/nginx-1.19.2.tar.gz во время процесса сборки. Вы можете изменить версию файла или расширение, изменив его только в одном месте благодаря Arg Инструкция.
  • Добавить Инструкция не извлекает файлы, полученные из Интернета по умолчанию, поэтому использование Tar на линии 18.

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

docker image build --tag custom-nginx:built .

# Step 1/9 : FROM ubuntu:latest
#  ---> d70eaf7277ea
# Step 2/9 : RUN apt-get update &&     apt-get install build-essential                    libpcre3                     libpcre3-dev                     zlib1g                     zlib1g-dev                     libssl-dev                     -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> cbe1ced3da11
### LONG INSTALLATION STUFF GOES HERE ###
# Step 3/9 : ARG FILENAME="nginx-1.19.2"
#  ---> Running in 33b62a0e9ffb
# Removing intermediate container 33b62a0e9ffb
#  ---> fafc0aceb9c8
# Step 4/9 : ARG EXTENSION="tar.gz"
#  ---> Running in 5c32eeb1bb11
# Removing intermediate container 5c32eeb1bb11
#  ---> 36efdf6efacc
# Step 5/9 : ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
# Downloading [==================================================>]  1.049MB/1.049MB
#  ---> dba252f8d609
# Step 6/9 : RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}
#  ---> Running in 2f5b091b2125
### LONG EXTRACTION STUFF GOES HERE ###
# Removing intermediate container 2f5b091b2125
#  ---> 2c9a325d74f1
# Step 7/9 : RUN cd ${FILENAME} &&     ./configure         --sbin-path=/usr/bin/nginx         --conf-path=/etc/nginx/nginx.conf         --error-log-path=/var/log/nginx/error.log         --http-log-path=/var/log/nginx/access.log         --with-pcre         --pid-path=/var/run/nginx.pid         --with-http_ssl_module &&     make && make install
#  ---> Running in 11cc82dd5186
### LONG CONFIGURATION AND BUILD STUFF GOES HERE ###
# Removing intermediate container 11cc82dd5186
#  ---> 6c122e485ec8
# Step 8/9 : RUN rm -rf /${FILENAME}}
#  ---> Running in 04102366960b
# Removing intermediate container 04102366960b
#  ---> 6bfa35420a73
# Step 9/9 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in 63ee44b571bb
# Removing intermediate container 63ee44b571bb
#  ---> 4ce79556db1b
# Successfully built 4ce79556db1b
# Successfully tagged custom-nginx:built

Теперь вы должны иметь возможность запускать контейнер, используя Custom-Nginx: построен изображение.

docker container run --rm --detach --name custom-nginx-built --publish 8080:80 custom-nginx:built

# 90ccdbc0b598dddc4199451b2f30a942249d85a8ed21da3c8d14612f17eed0aa

docker container ls

# CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                  NAMES
# 90ccdbc0b598        custom-nginx:built   "nginx -g 'daemon of…"   2 minutes ago       Up 2 minutes        0.0.0.0:8080->80/tcp   custom-nginx-built

Контейнер с использованием Custom-Nginx: STORKET-V2 Изображение было успешно запущено. Контейнер должен быть доступен в http://127.0.0.1:8080 сейчас.

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

Как оптимизировать образы докера

Изображение, которое мы встроенные в последнем подраздельном разделе, это функционально, но очень неочищено. Чтобы доказать свою точку зрения, давайте посмотрим на размер изображения, используя Изображение ls команда:

docker image ls

# REPOSITORY         TAG       IMAGE ID       CREATED          SIZE
# custom-nginx       built     1f3aaf40bb54   16 minutes ago   343MB

Для изображения, содержащего только Nginx, это слишком много. Если вы вытащите официальный образ и проверьте его размер, вы увидите, насколько он маленький:

docker image pull nginx:stable

# stable: Pulling from library/nginx
# a076a628af6f: Pull complete 
# 45d7b5d3927d: Pull complete 
# 5e326fece82e: Pull complete 
# 30c386181b68: Pull complete 
# b15158e9ebbe: Pull complete 
# Digest: sha256:ebd0fd56eb30543a9195280eb81af2a9a8e6143496accd6a217c14b06acd1419
# Status: Downloaded newer image for nginx:stable
# docker.io/library/nginx:stable

docker image ls

# REPOSITORY         TAG       IMAGE ID       CREATED          SIZE
# custom-nginx       built     1f3aaf40bb54   25 minutes ago   343MB
# nginx              stable    b9e1dc12387a   11 days ago      133MB

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

FROM ubuntu:latest

RUN apt-get update && \
    apt-get install build-essential\ 
                    libpcre3 \
                    libpcre3-dev \
                    zlib1g \
                    zlib1g-dev \
                    libssl1.1 \
                    libssl-dev \
                    -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"

ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .

RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}

RUN cd ${FILENAME} && \
    ./configure \
        --sbin-path=/usr/bin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --http-log-path=/var/log/nginx/access.log \
        --with-pcre \
        --pid-path=/var/run/nginx.pid \
        --with-http_ssl_module && \
    make && make install

RUN rm -rf /${FILENAME}}

CMD ["nginx", "-g", "daemon off;"]

Как вы можете увидеть на линии 3, Беги Инструкция устанавливает много вещей. Хотя эти пакеты необходимы для строительства Nginx от источника, они не нужны для его работы.

Из 6 пакетов, которые мы установили, только два необходимы для работы Nginx. Это libpcre3 и zlib1g Отказ Таким образом, лучшая идея будет удалить другие пакеты после выполнения процесса сборки.

Чтобы сделать это, обновите свой Dockerfile следующим образом:

FROM ubuntu:latest

EXPOSE 80

ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"

ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .

RUN apt-get update && \
    apt-get install build-essential \ 
                    libpcre3 \
                    libpcre3-dev \
                    zlib1g \
                    zlib1g-dev \
                    libssl1.1 \
                    libssl-dev \
                    -y && \
    tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} && \
    cd ${FILENAME} && \
    ./configure \
        --sbin-path=/usr/bin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --http-log-path=/var/log/nginx/access.log \
        --with-pcre \
        --pid-path=/var/run/nginx.pid \
        --with-http_ssl_module && \
    make && make install && \
    cd / && rm -rfv /${FILENAME} && \
    apt-get remove build-essential \ 
                    libpcre3-dev \
                    zlib1g-dev \
                    libssl-dev \
                    -y && \
    apt-get autoremove -y && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

CMD ["nginx", "-g", "daemon off;"]

Как вы можете видеть, на линии 10 единого Беги Инструкция делает все необходимое тяжелое подъема. Точная цепочка событий выглядит следующим образом:

  • От линии 10 до линии 17, все необходимые пакеты устанавливаются.
  • В строке 18 извлекается исходный код, и загруженный архив удаляется.
  • Из строки 19 до линии 28, Nginx настроен, создан и установлен в системе.
  • В строке 29 извлеченные файлы из загруженного архива удаляются.
  • Из строки 30 до линии 36 все ненужные пакеты удаляют, и кэш очищен. libpcre3 и zlib1g Пакеты необходимы для работы Nginx, поэтому мы сохраняем их.

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

Если вы устанавливаете пакеты, а затем удалите их в отдельном Беги Инструкции, они будут жить в отдельных слоях изображения. Хотя окончательное изображение не будет иметь удаленные пакеты, их размер все еще будет добавлен к окончательному изображению, поскольку они существуют в одном из слоев, состоящих из изображения. Поэтому убедитесь, что вы делаете такие изменения на одном слое.

Давайте построим изображение, используя это Dockerfile и увидеть различия.

docker image build --tag custom-nginx:built .

# Sending build context to Docker daemon  1.057MB
# Step 1/7 : FROM ubuntu:latest
#  ---> f63181f19b2f
# Step 2/7 : EXPOSE 80
#  ---> Running in 006f39b75964
# Removing intermediate container 006f39b75964
#  ---> 6943f7ef9376
# Step 3/7 : ARG FILENAME="nginx-1.19.2"
#  ---> Running in ffaf89078594
# Removing intermediate container ffaf89078594
#  ---> 91b5cdb6dabe
# Step 4/7 : ARG EXTENSION="tar.gz"
#  ---> Running in d0f5188444b6
# Removing intermediate container d0f5188444b6
#  ---> 9626f941ccb2
# Step 5/7 : ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
# Downloading [==================================================>]  1.049MB/1.049MB
#  ---> a8e8dcca1be8
# Step 6/7 : RUN apt-get update &&     apt-get install build-essential                     libpcre3                     libpcre3-dev                     zlib1g                     zlib1g-dev                     libssl-dev                     -y &&     tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} &&     cd ${FILENAME} &&     ./configure         --sbin-path=/usr/bin/nginx         --conf-path=/etc/nginx/nginx.conf         --error-log-path=/var/log/nginx/error.log         --http-log-path=/var/log/nginx/access.log         --with-pcre         --pid-path=/var/run/nginx.pid         --with-http_ssl_module &&     make && make install &&     cd / && rm -rfv /${FILENAME} &&     apt-get remove build-essential                     libpcre3-dev                     zlib1g-dev                     libssl-dev                     -y &&     apt-get autoremove -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> Running in e5675cad1260
### LONG INSTALLATION AND BUILD STUFF GOES HERE ###
# Removing intermediate container e5675cad1260
#  ---> dc7e4161f975
# Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in b579e4600247
# Removing intermediate container b579e4600247
#  ---> 512aa6a95a93
# Successfully built 512aa6a95a93
# Successfully tagged custom-nginx:built

docker image ls

# REPOSITORY         TAG       IMAGE ID       CREATED              SIZE
# custom-nginx       built     512aa6a95a93   About a minute ago   81.6MB
# nginx              stable    b9e1dc12387a   11 days ago          133MB

Как видите, размер изображения ушел от 343 МБ до 81,6 МБ. Официальное изображение 133 МБ. Это довольно оптимизированная сборка, но мы можем немного пойти немного в следующем подразделе.

Обнимая альпийский Linux

Если вы уже некоторое время возились контейнерами, вы, возможно, слышали о том, что называется Alpine Linux Отказ Это полнофункциональный Linux Распределение как Ubuntu , Debian или Федора Отказ

Но хорошая вещь о альпийском языке в том, что он построен вокруг мускул Libc и Bitebox и легкий. Где последние Ubuntu Изображение весит около 28 МБ, альпийский 2,8 МБ.

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

Хотя не в качестве удобства пользователя, как другие коммерческие распределения, переход к альпину все еще очень прост. В этом подсечении вы узнаете о воссоздании Custom-Nginx Изображение с использованием альпийского изображения в качестве его базы.

Откройте свой Dockerfile и обновить его контент следующим образом:

FROM alpine:latest

EXPOSE 80

ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"

ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .

RUN apk add --no-cache pcre zlib && \
    apk add --no-cache \
            --virtual .build-deps \
            build-base \ 
            pcre-dev \
            zlib-dev \
            openssl-dev && \
    tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} && \
    cd ${FILENAME} && \
    ./configure \
        --sbin-path=/usr/bin/nginx \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --http-log-path=/var/log/nginx/access.log \
        --with-pcre \
        --pid-path=/var/run/nginx.pid \
        --with-http_ssl_module && \
    make && make install && \
    cd / && rm -rfv /${FILENAME} && \
    apk del .build-deps

CMD ["nginx", "-g", "daemon off;"]

Код практически идентичен, за исключением нескольких изменений. Я буду перечислять изменения и объяснять их, как я иду:

  • Вместо использования apt-get install Для установки пакетов мы используем APK Добавить Отказ - Нет-кэш Опция означает, что загруженный пакет не будет кэширован. Точно так же мы будем использовать apk del вместо apt-get Удалить удалить пакеты.
  • --virtual Вариант для APK Добавить Команда используется для объединения куча пакетов в один виртуальный пакет для облегчения управления. Пакеты, которые необходимы только для построения программы, помечены как .Build-DEPS которые затем удаляются на линии 29, выполняя apk del .build-dems команда. Вы можете узнать больше о виртуальные в официальных документах.
  • Имена пакетов здесь немного отличаются. Обычно каждое дистрибутив Linux имеет свой репозиторий пакета, доступный каждому, где вы можете искать пакеты. Если вы знаете, что пакеты, необходимые для определенной задачи, вы можете просто отправиться в назначенный репозиторий для распределения и поиска его. Вы можете Посмотрите на альпийские пакеты Linux здесь Отказ

Теперь постройте новое изображение, используя этот Dockerfile и увидеть разницу в размере файла:

docker image build --tag custom-nginx:built .

# Sending build context to Docker daemon  1.055MB
# Step 1/7 : FROM alpine:latest
#  ---> 7731472c3f2a
# Step 2/7 : EXPOSE 80
#  ---> Running in 8336cfaaa48d
# Removing intermediate container 8336cfaaa48d
#  ---> d448a9049d01
# Step 3/7 : ARG FILENAME="nginx-1.19.2"
#  ---> Running in bb8b2eae9d74
# Removing intermediate container bb8b2eae9d74
#  ---> 87ca74f32fbe
# Step 4/7 : ARG EXTENSION="tar.gz"
#  ---> Running in aa09627fe48c
# Removing intermediate container aa09627fe48c
#  ---> 70cb557adb10
# Step 5/7 : ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
# Downloading [==================================================>]  1.049MB/1.049MB
#  ---> b9790ce0c4d6
# Step 6/7 : RUN apk add --no-cache pcre zlib &&     apk add --no-cache             --virtual .build-deps             build-base             pcre-dev             zlib-dev             openssl-dev &&     tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} &&     cd ${FILENAME} &&     ./configure         --sbin-path=/usr/bin/nginx         --conf-path=/etc/nginx/nginx.conf         --error-log-path=/var/log/nginx/error.log         --http-log-path=/var/log/nginx/access.log         --with-pcre         --pid-path=/var/run/nginx.pid         --with-http_ssl_module &&     make && make install &&     cd / && rm -rfv /${FILENAME} &&     apk del .build-deps
#  ---> Running in 0b301f64ffc1
### LONG INSTALLATION AND BUILD STUFF GOES HERE ###
# Removing intermediate container 0b301f64ffc1
#  ---> dc7e4161f975
# Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in b579e4600247
# Removing intermediate container b579e4600247
#  ---> 3e186a3c6830
# Successfully built 3e186a3c6830
# Successfully tagged custom-nginx:built

docker image ls

# REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
# custom-nginx       built     3e186a3c6830   8 seconds ago   12.8MB

Где версия Ubuntu была 81,6 МБ, альпийский наступил до 12,8 МБ, что является огромным усилением. Помимо APK Менеджер по пакетам, есть некоторые другие вещи, которые отличаются в альпийском от Ubuntu, но они не такие большие сделки. Вы можете просто найти Интернет, когда вы застряли.

Как создать исполняемые изображения Docker

В предыдущем разделе вы работали с FHSINCHY/RMBYEXT изображение. В этом разделе вы узнаете, как сделать такое исполняемое изображение.

Для начала открыть каталог, в котором вы клонировали репозиторий, пришел с этой книгой. Код для RMbyext Приложение проживает внутри подсчетов с тем же именем.

Прежде чем начать работать на Dockerfile Найдите минутку, чтобы спланировать то, что должно быть окончательный выход. На мой взгляд, это должно быть как что-то вроде этого:

  • Изображение должно иметь предварительно установленное Python.
  • Он должен содержать копию моего RMbyext скрипт
  • Рабочий каталог должен быть установлен, где будет выполняться скрипт.
  • RMbyext Сценарий должен быть установлен в качестве точки входа, поэтому изображение может принимать удлинительные имена в качестве аргументов.

Чтобы создать вышеупомянутое изображение, примите следующие шаги:

  • Получите хорошее базовое изображение для бега сценариев Python, как Python Отказ
  • Настройка рабочего каталога до легкодоступного каталога.
  • Установите Git так, чтобы скрипт был установлен с моего репозитория GitHUB.
  • Установите скрипт, используя git и pip.
  • Избавьтесь от ненужных пакетов сборки.
  • Установить RMbyext Как точка входа для этого изображения.

Теперь создайте новый Dockerfile внутри RMbyext каталог и поместить следующий код в нем:

FROM python:3-alpine

WORKDIR /zone

RUN apk add --no-cache git && \
    pip install git+https://github.com/fhsinchy/rmbyext.git#egg=rmbyext && \
    apk del git

ENTRYPOINT [ "rmbyext" ]

Объяснение инструкций в этом файле следующим образом:

  • От Наборы инструкций Python В качестве базового изображения, сделав идеальную среду для беговых сценариев Python. 3-ALPINE Тег указывает, что вы хотите, чтобы альпийский вариант Python 3.
  • Workdir Инструкция Устанавливает рабочий каталог по умолчанию для /зона здесь. Название рабочего каталога здесь совершенно случайно. Я нашел зону, чтобы быть приспособленным именем, вы можете использовать все, что вы хотите.
  • Учитывая RMbyext Сценарий установлен из GitHub, Гит это зависимость времени установки. Беги Инструкция по линии 5 Установить Гит затем устанавливает RMbyext Сценарий с использованием Git и Pip. Это также избавляется от Гит после.
  • Наконец на линии 9, Выходная точка Инструкция устанавливает RMbyext Сценарий как точка входа для этого изображения.

В этом досле один файл линии 9 – это магия, которая превращает это, казалось бы, нормальное изображение в исполняемое. Теперь, чтобы построить изображение, которое вы можете выполнить следующую команду:

docker image build --tag rmbyext .

# Sending build context to Docker daemon  2.048kB
# Step 1/4 : FROM python:3-alpine
# 3-alpine: Pulling from library/python
# 801bfaa63ef2: Already exists 
# 8723b2b92bec: Already exists 
# 4e07029ccd64: Already exists 
# 594990504179: Already exists 
# 140d7fec7322: Already exists 
# Digest: sha256:7492c1f615e3651629bd6c61777e9660caa3819cf3561a47d1d526dfeee02cf6
# Status: Downloaded newer image for python:3-alpine
#  ---> d4d4f50f871a
# Step 2/4 : WORKDIR /zone
#  ---> Running in 454374612a91
# Removing intermediate container 454374612a91
#  ---> 7f7e49bc98d2
# Step 3/4 : RUN apk add --no-cache git &&     pip install git+https://github.com/fhsinchy/rmbyext.git#egg=rmbyext &&     apk del git
#  ---> Running in 27e2e96dc95a
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container 27e2e96dc95a
#  ---> 3c7389432e36
# Step 4/4 : ENTRYPOINT [ "rmbyext" ]
#  ---> Running in f239bbea1ca6
# Removing intermediate container f239bbea1ca6
#  ---> 1746b0cedbc7
# Successfully built 1746b0cedbc7
# Successfully tagged rmbyext:latest

docker image ls

# REPOSITORY         TAG        IMAGE ID       CREATED         SIZE
# rmbyext            latest     1746b0cedbc7   4 minutes ago   50.9MB

Здесь я не предоставил ни теги после имени изображения, поэтому изображение было помечено как Последнее по умолчанию. Вы должны иметь возможность запускать изображение, когда вы видели в предыдущем разделе. Не забудьте обратиться к фактическому названию изображения, а не FHSINCHY/RMBYEXT здесь.

Как поделиться своими изображениями Docker онлайн

Теперь, когда вы знаете, как сделать изображения, пришло время поделиться с ними с миром. Обмен изображениями онлайн легко. Все, что вам нужно, это учетная запись в любой из онлайн-реестров. Я буду использовать Докер Хаб здесь.

Перейдите к Зарегистрируйтесь Страница и создайте бесплатную учетную запись. Бесплатная учетная запись позволяет размещать неограниченные публичные репозитории и один частный репозиторий.

Как только вы создали учетную запись, вам придется войти в нее, используя Docker CLI. Так что откройте свой терминал и выполните следующую команду, чтобы сделать это:

docker login

# Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
# Username: fhsinchy
# Password: 
# WARNING! Your password will be stored unencrypted in /home/fhsinchy/.docker/config.json.
# Configure a credential helper to remove this warning. See
# https://docs.docker.com/engine/reference/commandline/login/#credentials-store
#
# Login Succeeded

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

Для того, чтобы поделиться изображением онлайн, изображение должно быть помечено. Вы уже узнали о метке в предыдущем подразделе. Просто чтобы обновить вашу память, общий синтаксис для --tag или -t Вариант выглядит следующим образом:

--tag :

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

Чтобы поделиться изображением онлайн, вам придется пометить его после <Имя пользователя Docker Hub>/<Имя изображения>: <Тег изображения> синтаксис. Мое имя пользователя Fhsinchy Так что команда будет выглядеть так:

docker image build --tag fhsinchy/custom-nginx:latest --file Dockerfile.built .

# Step 1/9 : FROM ubuntu:latest
#  ---> d70eaf7277ea
# Step 2/9 : RUN apt-get update &&     apt-get install build-essential                    libpcre3                     libpcre3-dev                     zlib1g                     zlib1g-dev                     libssl-dev                     -y &&     apt-get clean && rm -rf /var/lib/apt/lists/*
#  ---> cbe1ced3da11
### LONG INSTALLATION STUFF GOES HERE ###
# Step 3/9 : ARG FILENAME="nginx-1.19.2"
#  ---> Running in 33b62a0e9ffb
# Removing intermediate container 33b62a0e9ffb
#  ---> fafc0aceb9c8
# Step 4/9 : ARG EXTENSION="tar.gz"
#  ---> Running in 5c32eeb1bb11
# Removing intermediate container 5c32eeb1bb11
#  ---> 36efdf6efacc
# Step 5/9 : ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
# Downloading [==================================================>]  1.049MB/1.049MB
#  ---> dba252f8d609
# Step 6/9 : RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}
#  ---> Running in 2f5b091b2125
### LONG EXTRACTION STUFF GOES HERE ###
# Removing intermediate container 2f5b091b2125
#  ---> 2c9a325d74f1
# Step 7/9 : RUN cd ${FILENAME} &&     ./configure         --sbin-path=/usr/bin/nginx         --conf-path=/etc/nginx/nginx.conf         --error-log-path=/var/log/nginx/error.log         --http-log-path=/var/log/nginx/access.log         --with-pcre         --pid-path=/var/run/nginx.pid         --with-http_ssl_module &&     make && make install
#  ---> Running in 11cc82dd5186
### LONG CONFIGURATION AND BUILD STUFF GOES HERE ###
# Removing intermediate container 11cc82dd5186
#  ---> 6c122e485ec8
# Step 8/9 : RUN rm -rf /${FILENAME}}
#  ---> Running in 04102366960b
# Removing intermediate container 04102366960b
#  ---> 6bfa35420a73
# Step 9/9 : CMD ["nginx", "-g", "daemon off;"]
#  ---> Running in 63ee44b571bb
# Removing intermediate container 63ee44b571bb
#  ---> 4ce79556db1b
# Successfully built 4ce79556db1b
# Successfully tagged fhsinchy/custom-nginx:latest

В этой команде fhsinchy/custom-nginx это репозиторий изображения и Последнее это тег. Имя изображения может быть все, что вы хотите, и не может быть изменен, как только вы загрузили изображение. Тег может быть изменен всякий раз, когда вы хотите, и обычно отражают версию программного обеспечения или разных видов сборки.

Возьми Узел изображение в качестве примера. Узел: LTS Изображение относится к долгосрочной поддержке версии Node.js, тогда как Узел: LTS-Alpine Версия относится к версии Node.js, построенной для Alpine Linux, которая намного меньше, чем обычный.

Если вы не даете изображения любой тег, он будет автоматически помечен как Последнее Отказ Но это не значит, что Последнее Тег всегда будет ссылаться на последнюю версию. Если по какой-то причине вы явно тег старая версия изображения как Последнее Затем Docker не приложит никакие дополнительные усилия, чтобы пересечь это.

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

docker image push :

Так что в моем случае команда будет следующим:

docker image push fhsinchy/custom-nginx:latest

# The push refers to repository [docker.io/fhsinchy/custom-nginx]
# 4352b1b1d9f5: Pushed 
# a4518dd720bd: Pushed 
# 1d756dc4e694: Pushed 
# d7a7e2b6321a: Pushed 
# f6253634dc78: Mounted from library/ubuntu 
# 9069f84dbbe9: Mounted from library/ubuntu 
# bacd3af13903: Mounted from library/ubuntu 
# latest: digest: sha256:ffe93440256c9edb2ed67bf3bba3c204fec3a46a36ac53358899ce1a9eee497a size: 1788

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

Как контейнеризировать приложение JavaScript

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

В этом подраздел вы будете работать с исходным кодом FHSINCHY/HELLO-DOCK Изображение, с которым вы работали в предыдущем разделе. В процессе контейнера к этому очень простому приложению вы будете введены в объемы и многоядерные сборки, две из самых важных концепций в Docker.

Как написать Development DockerFile

Для начала открыть каталог, в котором вы клонировали репозиторий, пришел с этой книгой. Код для Привет-док Приложение проживает внутри подсчетов с тем же именем.

Это очень простой проект JavaScript, питающийся от Vitejs/Vite проект. Не волнуйтесь, хотя вам не нужно знать JavaScript или Vite, чтобы пройти через этот подраздел. Имея основное понимание Node.js и NPM будет достаточно.

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

  • Получите хорошее базовое изображение для запуска приложений JavaScript, например Узел Отказ
  • Установите рабочий каталог по умолчанию внутри изображения.
  • Скопируйте Package.json файл на изображение.
  • Установите необходимые зависимости.
  • Скопируйте остальные файлы проекта.
  • Начать Вите Сервер разработки путем выполнения NPM запустить dev команда.

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

Теперь, если вы поставили вышеупомянутый план внутри Dockerfile.dev , файл должен выглядеть следующим образом:

FROM node:lts-alpine

EXPOSE 3000

USER node

RUN mkdir -p /home/node/app

WORKDIR /home/node/app

COPY ./package.json .
RUN npm install

COPY . .

CMD [ "npm", "run", "dev" ]

Объяснение этого кода выглядит следующим образом:

  • От Инструкция здесь устанавливает официальный образ Node.js в качестве основы, предоставляя вам всю доброту Node.js, необходимых для запуска любого приложения JavaScript. LTS-ALPINE Тег указывает, что вы хотите использовать альпийский вариант, долгосрочную поддержку версии изображения. Доступные теги и необходимая документация для изображения можно найти на Узел Страница HUB.
  • Пользователь Инструкция Устанавливает пользователя по умолчанию для изображения на Узел Отказ По умолчанию Docker управляет контейнерами как пользователь root. Но по словам Докер и Node.js лучшие практики Это может представлять угрозу безопасности. Таким образом, это лучшее представление о том, чтобы работать как пользователь без root, когда это возможно. Изображение узла поставляется с пользователем Non-root с именем Узел который вы можете установить как пользователь по умолчанию, используя Пользователь Инструкция.
  • Run mkdir -p/home/node/app Инструкция создает каталог под названием приложение Внутри домашнего каталога Узел Пользователь. Домашний каталог для любого пользователем без root в Linux обычно /home/<имя пользователя> по умолчанию.
  • Тогда Workdir Инструкция Устанавливает рабочий каталог по умолчанию для вновь созданного /Home/Node/App каталог. По умолчанию рабочий каталог любого изображения является корнем. Вы не хотите, чтобы никакие ненужные файлы распыляются по всему корневому каталогу, делаете ли вы? Следовательно, вы меняете рабочий каталог по умолчанию на что-то более разумное, как /Home/Node/App или что угодно. Этот рабочий каталог будет применим к любому последующему Скопировать , Добавить , Беги и CMD инструкции.
  • Скопировать Инструкция здесь копирует Package.json Файл, который содержит информацию о всех необходимых зависимостях для этого приложения. Беги Инструкция выполняет NPM установить Команда, которая является командой по умолчанию для установки зависимостей с помощью A Package.json Файл в Node.js проекты. Отказ В конце представляет рабочий каталог.
  • Второй Скопировать Инструкция копирует остальную часть содержимого из текущего каталога ( . ) файловой системы хоста в рабочий каталог ( . ) Внутри изображения.
  • Наконец, CMD Инструкция здесь устанавливает команду по умолчанию для этого изображения, которое является NPM запустить dev написано в exec форма.
  • Вите Сервер разработки по умолчанию работает на порту 3000 и добавляя Выставлять Команда казалась хорошей идеей, так что вы идете.

Теперь, чтобы построить изображение из этого Dockerfile.dev Вы можете выполнить следующую команду:

docker image build --file Dockerfile.dev --tag hello-dock:dev .

# Step 1/7 : FROM node:lts
#  ---> b90fa0d7cbd1
# Step 2/7 : EXPOSE 3000
#  ---> Running in 722d639badc7
# Removing intermediate container 722d639badc7
#  ---> e2a8aa88790e
# Step 3/7 : WORKDIR /app
#  ---> Running in 998e254b4d22
# Removing intermediate container 998e254b4d22
#  ---> 6bd4c42892a4
# Step 4/7 : COPY ./package.json .
#  ---> 24fc5164a1dc
# Step 5/7 : RUN npm install
#  ---> Running in 23b4de3f930b
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container 23b4de3f930b
#  ---> c17ecb19a210
# Step 6/7 : COPY . .
#  ---> afb6d9a1bc76
# Step 7/7 : CMD [ "npm", "run", "dev" ]
#  ---> Running in a7ff529c28fe
# Removing intermediate container a7ff529c28fe
#  ---> 1792250adb79
# Successfully built 1792250adb79
# Successfully tagged hello-dock:dev

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

docker container run \
    --rm \
    --detach \
    --publish 3000:3000 \
    --name hello-dock-dev \
    hello-dock:dev

# 21b9b1499d195d85e81f0e8bce08f43a64b63d589c5f15cbbd0b9c0cb07ae268

Теперь посетите http://127.0.0.1:3000 чтобы увидеть Привет-док Приложение в действии.

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

Как работать с креплениями Bind в Docker

Если вы работали с любым интерфейсом JavaScript Framework, вы должны знать, что серверы разработки в этих рамках обычно поставляются с функцией горячей перезагрузки. То есть, если вы внесите изменения в свой код, сервер будет перезагружаться, автоматически отражая любые изменения, которые вы сделали сразу.

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

Чтобы решить эту проблему, вы можете снова использовать привязать крепление Отказ Используя крепления BING, вы можете легко установить одну из ваших местных каталогов файловой системы внутри контейнера. Вместо того, чтобы сделать копию локальной файловой системы, крепление BING может ссылаться на локальную файловую систему непосредственно изнутри контейнера.

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

Вы уже узнали в Работа с исполняемыми изображениями Подборка, крепления связывания могут быть созданы с помощью --volume или -V Вариант для Контейнер работает или Старт контейнера команды. Просто чтобы напомнить вам, общий синтаксис выглядит следующим образом:

--volume ::

Остановите, что вы начали ранее Hello-Dock-dev Контейнер и начните новый контейнер, выполнив следующую команду:

docker container run \
    --rm \
    --publish 3000:3000 \
    --name hello-dock-dev \
    --volume $(pwd):/home/node/app \
    hello-dock:dev

# sh: 1: vite: not found
# npm ERR! code ELIFECYCLE
# npm ERR! syscall spawn
# npm ERR! file sh
# npm ERR! errno ENOENT
# npm ERR! hello-dock@0.0.0 dev: `vite`
# npm ERR! spawn ENOENT
# npm ERR!
# npm ERR! Failed at the hello-dock@0.0.0 dev script.
# npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
# npm WARN Local package.json exists, but node_modules missing, did you mean to install?

Имейте в виду, я опустил --detach Вариант, и это демонстрировать очень важный момент. Как видите, приложение вообще не работает.

Это потому, что хотя использование объема решает проблему горячих перезарядков, он вводит другую проблему. Если у вас есть какой-либо предыдущий опыт работы с Node.js, вы можете знать, что зависимости проекта Node.js живут внутри node_modules каталог на корне проекта.

Теперь, когда вы устанавливаете Root Project в локальной файловой системе в качестве громкости внутри контейнера, содержимое внутри контейнера заменяется вместе с node_modules каталог, содержащий все зависимости. Это означает, что Вите Пакет пропал без вести.

Как работать с анонимными томами в докере

Эта проблема может быть решена с использованием анонимного объема. Анонимный том идентичен для крепления Bind, за исключением того, что вам не нужно указывать исходный каталог здесь. Общий синтаксис для создания анонимного объема выглядит следующим образом:

--volume :

Так что финальная команда для запуска Привет-док Контейнер с обеими объемами должен быть следующим:

docker container run \
    --rm \
    --detach \
    --publish 3000:3000 \
    --name hello-dock-dev \
    --volume $(pwd):/home/node/app \
    --volume /home/node/app/node_modules \
    hello-dock:dev

# 53d1cfdb3ef148eb6370e338749836160f75f076d0fbec3c2a9b059a8992de8b

Здесь докер займет весь node_modules Каталог изнутри контейнера и заправить его в каком-то другом каталоге, управляемом Docker Daemon на вашей файловой системе хоста и установит этот каталог AS node_modules внутри контейнера.

Как выполнить многоядерные сборки в Docker

До сих пор в этом разделе вы построили изображение для запуска приложения JavaScript в режиме разработки. Теперь, если вы хотите создать изображение в производственном режиме, появятся некоторые новые вызовы.

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

В режиме производства NPM запустить сборку Команда компилирует весь ваш код JavaScript в некоторые статические файлы HTML, CSS и JavaScript. Чтобы запустить эти файлы, вам не нужен узел или любые другие зависимости выполнения. Все, что вам нужно, это сервер, такой как nginx Например.

Чтобы создать изображение, в котором приложение работает в режиме производства, вы можете принять следующие шаги:

  • Использовать Узел в качестве базового изображения и создайте приложение.
  • Установить nginx Внутри изображения узла и используйте, что для обслуживания статических файлов.

Этот подход полностью действителен. Но проблема в том, что Узел Изображение большая, и большинство вещей, которые он несет не нужен, чтобы обслуживать ваши статические файлы. Лучший подход к этому сценарию выглядит следующим образом:

  • Использовать Узел Изображение в качестве основы и построить приложение.
  • Скопируйте файлы, созданные с помощью Узел Изображение для nginx изображение.
  • Создайте окончательное изображение на основе nginx и отказаться от всех Узел Связанные вещи.

Таким образом, ваше изображение содержит только файлы, которые необходимы, и становится действительно удобным.

Этот подход – это многостоятельная сборка. Чтобы выполнить такую сборку, создайте новый Dockerfile Внутри вашего Привет-док каталог проекта и поместить следующий контент в нем:

FROM node:lts-alpine as builder

WORKDIR /app

COPY ./package.json ./
RUN npm install

COPY . .
RUN npm run build

FROM nginx:stable-alpine

EXPOSE 80

COPY --from=builder /app/dist /usr/share/nginx/html

Как вы можете увидеть Dockerfile очень похоже на ваши предыдущие с несколькими странами. Объяснение этого файла выглядит следующим образом:

  • Линия 1 начинает первый этап сборки, используя Узел: LTS-Alpine как базовое изображение. как строитель Синтаксис назначает имя на этот этап, чтобы его можно было упомянуть позже.
  • Из строки 3 до линии 9, это стандартные вещи, которые вы видели много раз ранее. Запустите NPM Run Build Команда фактически компилирует все приложение и заправляет его внутри /app/dist каталог, где /приложение рабочий каталог и /dist это выходной каталог по умолчанию для Вите Приложения.
  • Линия 11 начинается второй этап сборки, используя nginx: стабильный альпийский как базовое изображение.
  • Сервер Nginx работает на порту 80 по умолчанию, так что линия Выдержать 80 добавлен.
  • Последняя строка – Скопировать Инструкция. - из построителя Часть указывает, что вы хотите скопировать некоторые файлы из строитель сцена. После этого это стандартная команда копирования, где /app/dist это источник и /usr/share/nginx/html это пункт назначения. Используемый здесь пункт назначения – путь сайта по умолчанию для Nginx, поэтому любой статический файл, который вы помещаете внутри, будет автоматически подан.

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

docker image build --tag hello-dock:prod .

# Step 1/9 : FROM node:lts-alpine as builder
#  ---> 72aaced1868f
# Step 2/9 : WORKDIR /app
#  ---> Running in e361c5c866dd
# Removing intermediate container e361c5c866dd
#  ---> 241b4b97b34c
# Step 3/9 : COPY ./package.json ./
#  ---> 6c594c5d2300
# Step 4/9 : RUN npm install
#  ---> Running in 6dfabf0ee9f8
# npm WARN deprecated fsevents@2.1.3: Please update to v 2.2.x
#
# > esbuild@0.8.29 postinstall /app/node_modules/esbuild
# > node install.js
#
# npm notice created a lockfile as package-lock.json. You should commit this file.
# npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/chokidar/node_modules/fsevents):
# npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
# npm WARN hello-dock@0.0.0 No description
# npm WARN hello-dock@0.0.0 No repository field.
# npm WARN hello-dock@0.0.0 No license field.
#
# added 327 packages from 301 contributors and audited 329 packages in 35.971s
#
# 26 packages are looking for funding
#   run `npm fund` for details
#
# found 0 vulnerabilities
#
# Removing intermediate container 6dfabf0ee9f8
#  ---> 21fd1b065314
# Step 5/9 : COPY . .
#  ---> 43243f95bff7
# Step 6/9 : RUN npm run build
#  ---> Running in 4d918cf18584
#
# > hello-dock@0.0.0 build /app
# > vite build
#
# - Building production bundle...
#
# [write] dist/index.html 0.39kb, brotli: 0.15kb
# [write] dist/_assets/docker-handbook-github.3adb4865.webp 12.32kb
# [write] dist/_assets/index.eabcae90.js 42.56kb, brotli: 15.40kb
# [write] dist/_assets/style.0637ccc5.css 0.16kb, brotli: 0.10kb
# - Building production bundle...
#
# Build completed in 1.71s.
#
# Removing intermediate container 4d918cf18584
#  ---> 187fb3e82d0d
# Step 7/9 : EXPOSE 80
#  ---> Running in b3aab5cf5975
# Removing intermediate container b3aab5cf5975
#  ---> d6fcc058cfda
# Step 8/9 : FROM nginx:stable-alpine
# stable: Pulling from library/nginx
# 6ec7b7d162b2: Already exists 
# 43876acb2da3: Pull complete 
# 7a79edd1e27b: Pull complete 
# eea03077c87e: Pull complete 
# eba7631b45c5: Pull complete 
# Digest: sha256:2eea9f5d6fff078ad6cc6c961ab11b8314efd91fb8480b5d054c7057a619e0c3
# Status: Downloaded newer image for nginx:stable
#  ---> 05f64a802c26
# Step 9/9 : COPY --from=builder /app/dist /usr/share/nginx/html
#  ---> 8c6dfc34a10d
# Successfully built 8c6dfc34a10d
# Successfully tagged hello-dock:prod

Как только изображение будет построено, вы можете запустить новый контейнер, выполнив следующую команду:

docker container run \
    --rm \
    --detach \
    --name hello-dock-prod \
    --publish 8080:80 \
    hello-dock:prod

# 224aaba432bb09aca518fdd0365875895c2f5121eb668b2e7b2d5a99c019b953

Запускное приложение должно быть доступно на http://127.0.0.1:8080 :

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

Как игнорировать ненужные файлы

Если вы работали с Гит Некоторое время вы можете знать о .gitignore Файлы в проектах. Они содержат список файлов и каталогов, которые будут исключены из репозитория.

Ну, у докера есть подобная концепция. .dockerignore Файл содержит список файлов и каталогов, которые будут исключены из сборки изображений. Вы можете найти предварительно созданный .dockerignore Файл в Привет-док каталог.

.git
*Dockerfile*
*docker-compose*
node_modules

Это .dockerignore Файл должен быть в контексте сборки. Упомянутые здесь файлы и каталоги будут игнорироваться Скопировать Инструкция. Но если вы делаете крепление Bind, .dockerignore Файл не будет иметь никакого эффекта. Я добавил .dockerignore Файлы, где это необходимо в репозитории проекта.

Основы манипулирования сетью в докере

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

Таким образом, в этом разделе книги вы познакомитесь с базовыми сетью с Docker, и вы будете работать в руках с небольшим многофункциональным проектом.

Ну, вы уже узнали в предыдущем разделе, что контейнеры являются изолированными средами. Теперь рассмотрим сценарий, где у вас есть Notes-API Приложение Powered by Express.js и а PostgreSQL Сервер базы данных работает в двух отдельных контейнерах.

Эти две контейнеры полностью изолированы друг от друга и не обрабатывают существование друг друга. Так как вы подключаете два? Не будет ли это проблемой?

Вы можете подумать о двух возможных решениях этой проблемы. Они следующие:

  • Доступ к серверу базы данных с помощью открытого порта.
  • Доступ к серверу базы данных с использованием его IP-адреса и порта по умолчанию.

Первый предполагает разоблачение порта из Postgres Контейнер и Notes-API подключу через это. Предположим, что открытый порт из Postgres Контейнер 5432. Теперь, если вы попытаетесь подключиться к 127.0.0.1:5432 изнутри Notes-API Контейнер, вы обнаружите, что Notes-API Не можете найти сервер базы данных вообще.

Причина в том, что когда вы говорите 127.0.0.1 внутри Notes-API Контейнер, вы просто ссылаетесь на localhost этого контейнера и этот контейнер только. Postgres Сервер просто там не существует. В результате Notes-API Приложение не удалось подключиться.

Второе решение, которое вы можете подумать, – найти точный IP-адрес Postgres Контейнер с использованием Контейнер проверяет Команда и используя это с портом. Предполагая название Postgres Контейнер Notes-API-DB-сервер Вы можете легко получить IP-адрес, выполнив следующую команду:

docker container inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}} {{end}}' notes-api-db-server

#  172.17.0.2

Теперь дал, что порт по умолчанию для Postgres это 5432 , вы можете легко получить доступ к серверу базы данных, подключив к 172.17.0.2:5432 от Notes-API контейнер.

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

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

Основы Docker Network

Сеть в Docker – еще один логический объект, такой как контейнер и изображение. Как и два других, есть множество команд под Дочсерская сеть Группа для манипулирования сетью.

Чтобы перечислить сети в вашей системе, выполните следующую команду:

docker network ls

# NETWORK ID     NAME      DRIVER    SCOPE
# c2e59f2b96bd   bridge    bridge    local
# 124dccee067f   host      host      local
# 506e3822bf1f   none      null      local

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

По умолчанию Docker имеет пять сетевых драйверов. Они следующие:

  • мост – драйвер сети по умолчанию в Docker. Это может быть использовано, когда несколько контейнеров работают в стандартном режиме и должны взаимодействовать друг с другом.
  • хозяин – полностью удаляет сетевую изоляцию. Любой контейнер работает под хозяин Сеть в основном прикреплена к сети хост-системы.
  • Нет – Этот драйвер отключает сетевые контейнеры в целом. Я еще не нашел никакого использования для этого.
  • наложение – Это используется для подключения нескольких Docker Daemons по компьютерам и отсутствует в объеме этой книги.
  • Macvlan – Позволяет присвоению MAC-адресов в контейнеры, что делает их функцией, такие как физические устройства в сети.

Есть также сторонние плагины, которые позволяют интегрировать Docker со специализированными сетевыми стеками. Из пяти упомянутых выше вы будете работать только с мост Сетевой драйвер в этой книге.

Как создать пользовательский мост в Docker

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

docker network ls

# NETWORK ID     NAME      DRIVER    SCOPE
# c2e59f2b96bd   bridge    bridge    local
# 124dccee067f   host      host      local
# 506e3822bf1f   none      null      local

Как видите, Docker поставляется с сетью моста по умолчанию с именем мост Отказ Любой управляемый контейнер будет автоматически прикреплен к этой сети мостов:

docker container run --rm --detach --name hello-dock --publish 8080:80 fhsinchy/hello-dock
# a37f723dad3ae793ce40f97eb6bb236761baa92d72a2c27c24fc7fda0756657d

docker network inspect --format='{{range .Containers}}{{.Name}}{{end}}' bridge
# hello-dock

Контейнеры, прикрепленные к сети моста по умолчанию, могут взаимодействовать друг с другом, используя IP-адреса, которые я уже обескуражен в предыдущем подразделе.

Однако пользовательский мост, однако, имеет несколько дополнительных функций по сравнению с одним. Согласно официальному Документы На этой теме некоторые заметные дополнительные функции следующие:

  • Пользовательские мосты обеспечивают автоматическое разрешение DNS между контейнерами: Это означает, что контейнеры, прикрепленные к той же сети, могут взаимодействовать друг с другом, используя имя контейнера. Так что, если у вас есть два контейнера по имени Notes-API и Notes-db Контейнер API сможет подключиться к контейнеру базы данных, используя Notes-db название.
  • Пользовательские мосты обеспечивают лучшую изоляцию: Все контейнеры прикреплены к сети моста по умолчанию по умолчанию, что может вызвать конфликты среди них. Прикрепление контейнеров к пользовательскому мосту может обеспечить лучшую изоляцию.
  • Контейнеры могут быть прикреплены и отделены от пользовательских сетей на лету: Во время срока службы контейнера вы можете подключить или отключить его от пользовательских сетей на лету. Чтобы удалить контейнер из сети мостов по умолчанию, вам нужно остановить контейнер и воссоздать его разными параметрами сети.

Теперь, когда вы узнали довольно много о пользовательской сети, пришло время создавать его для себя. Сеть может быть создана с помощью Сеть создавать команда. Общий синтаксис для команды выглядит следующим образом:

docker network create 

Чтобы создать сеть с именем Skynet Выполнить следующую команду:

docker network create skynet

# 7bd5f351aa892ac6ec15fed8619fc3bbb95a7dcdd58980c28304627c8f7eb070

docker network ls

# NETWORK ID     NAME     DRIVER    SCOPE
# be0cab667c4b   bridge   bridge    local
# 124dccee067f   host     host      local
# 506e3822bf1f   none     null      local
# 7bd5f351aa89   skynet   bridge    local

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

Как прикрепить контейнер к сети в Docker

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

docker network connect  

Подключить Привет-док Контейнер к Skynet Сеть, вы можете выполнить следующую команду:

docker network connect skynet hello-dock

docker network inspect --format='{{range .Containers}} {{.Name}} {{end}}' skynet

#  hello-dock

docker network inspect --format='{{range .Containers}} {{.Name}} {{end}}' bridge

#  hello-dock

Как вы можете видеть с выходов двух Сеть проверяет Команды, Привет-док Контейнер теперь прикреплен к обоим Skynet и по умолчанию мост сеть.

Второй способ подключения контейнера к сети – использование --network Вариант для Контейнер работает или Контейнер создает команды. Общий синтаксис для опции выглядит следующим образом:

--network 

Чтобы запустить другой Привет-док Контейнер, прикрепленный к той же сети, вы можете выполнить следующую команду:

docker container run --network skynet --rm --name alpine-box -it alpine sh

# lands you into alpine linux shell

/ # ping hello-dock

# PING hello-dock (172.18.0.2): 56 data bytes
# 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.191 ms
# 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.103 ms
# 64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.139 ms
# 64 bytes from 172.18.0.2: seq=3 ttl=64 time=0.142 ms
# 64 bytes from 172.18.0.2: seq=4 ttl=64 time=0.146 ms
# 64 bytes from 172.18.0.2: seq=5 ttl=64 time=0.095 ms
# 64 bytes from 172.18.0.2: seq=6 ttl=64 time=0.181 ms
# 64 bytes from 172.18.0.2: seq=7 ttl=64 time=0.138 ms
# 64 bytes from 172.18.0.2: seq=8 ttl=64 time=0.158 ms
# 64 bytes from 172.18.0.2: seq=9 ttl=64 time=0.137 ms
# 64 bytes from 172.18.0.2: seq=10 ttl=64 time=0.145 ms
# 64 bytes from 172.18.0.2: seq=11 ttl=64 time=0.138 ms
# 64 bytes from 172.18.0.2: seq=12 ttl=64 time=0.085 ms

--- hello-dock ping statistics ---
13 packets transmitted, 13 packets received, 0% packet loss
round-trip min/avg/max = 0.085/0.138/0.191 ms

Как видите, работает Ping Hello-Dock изнутри альпийская коробка Контейнерные работы, потому что обе контейнеры находятся под тем же пользовательской сетью мостов, и работает автоматическое разрешение DNS.

Имейте в виду, хотя, чтобы, чтобы автоматическое разрешение DNS работать, вы должны назначить пользовательские имена для контейнеров. Использование случайно сгенерированного имени не будет работать.

Как отсоединить контейнеры из сети в докере

В предыдущем подразделе вы узнали о прикреплении контейнеров к сети. В этом подраздел вы узнаете о том, как их отсоединить.

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

docker network disconnect  

Отсоединить Привет-док Контейнер из Skynet Сеть, вы можете выполнить следующую команду:

docker network disconnect skynet hello-dock

Так же, как Network Connect Команда, Сетевое отключение Команда не дает никакого вывода.

Как избавиться от сетей в Docker

Как и другие логические объекты в Docker, сети могут быть удалены с помощью Сеть RM команда. Общий синтаксис для команды выглядит следующим образом:

docker network rm 

Удалить Skynet Сеть из вашей системы, вы можете выполнить следующую команду:

docker network rm skynet

Вы также можете использовать Сетевой Brune Команда удалить любые неиспользуемые сети из вашей системы. У команды также есть -f или - Форс и или - Все параметры.

Как контейнеризировать многофункциональное приложение JavaScript

Теперь, когда вы узнали достаточно о сетях в Docker, в этом разделе вы научитесь контейнерировать полноценный многоконтонченный проект. Проект вы будете работать, это просто Notes-API Работает на Express.js и postgresql.

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

Как запустить сервер базы данных

Сервер базы данных в этом проекте является простым PostgreSQL Server и использует официальный Postgres изображение.

Согласно официальным документам, чтобы запустить контейнер с этим изображением, вы должны предоставить Postgres_password Переменная среды. Помимо этого, я также предоставим имя для базы данных по умолчанию, используя Postgrees_db Переменная среды. PostgreSQL по умолчанию слушает порта 5432 Так что вам нужно публиковать это тоже.

Для запуска сервера базы данных вы можете выполнить следующую команду:

docker container run \
    --detach \
    --name=notes-db \
    --env POSTGRES_DB=notesdb \
    --env POSTGRES_PASSWORD=secret \
    --network=notes-api-network \
    postgres:12

# a7b287d34d96c8e81a63949c57b83d7c1d71b5660c87f5172f074bd1606196dc

docker container ls

# CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS      NAMES
# a7b287d34d96   postgres:12   "docker-entrypoint.s…"   About a minute ago   Up About a minute   5432/tcp   notes-db

--env Вариант для Контейнер работает и Контейнер создает Команды могут быть использованы для предоставления переменных среды к контейнеру. Как видите, контейнер базы данных был успешно создан и работает сейчас.

Хотя контейнер работает, есть небольшая проблема. Базы данных, такие как PostgreSQL, Mongodb, и MySQL, сохраняют свои данные в каталоге. PostgreSQL использует /var/lib/postgresql/data каталог внутри контейнера для сохранения данных.

Теперь, если контейнер по какой-то причине уничтожен? Вы потеряете все ваши данные. Чтобы решить эту проблему, можно использовать названный объем.

Как работать с названными томами в докере

Раньше вы работали с монтажами связывания и анонимными объемами. Именный объем очень похож на анонимный том, за исключением того, что вы можете обратиться к названному тому, используя его имя.

Тома также являются логическими объектами в Docker и могут быть манипулированы с помощью командной строки. Том создать Команда может быть использована для создания именованного тома.

Общий синтаксис для команды выглядит следующим образом:

docker volume create 

Создать объем имени Notes-db-data Вы можете выполнить следующую команду:

docker volume create notes-db-data

# notes-db-data

docker volume ls

# DRIVER    VOLUME NAME
# local     notes-db-data

Этот объем теперь может быть установлен на /var/lib/postgresql/data внутри Notes-db контейнер. Сделать это, остановитесь и удалите Notes-db контейнер:

docker container stop notes-db

# notes-db

docker container rm notes-db

# notes-db

Теперь запустите новый контейнер и назначьте громкость, используя --volume или -V вариант.

docker container run \
    --detach \
    --volume notes-db-data:/var/lib/postgresql/data \
    --name=notes-db \
    --env POSTGRES_DB=notesdb \
    --env POSTGRES_PASSWORD=secret \
    --network=notes-api-network \
    postgres:12

# 37755e86d62794ed3e67c19d0cd1eba431e26ab56099b92a3456908c1d346791

Теперь проверьте Notes-db Контейнер, чтобы убедиться, что монтаж был успешным:

docker container inspect --format='{{range .Mounts}} {{ .Name }} {{end}}' notes-db

#  notes-db-data

Теперь данные будут безопасно храниться внутри Notes-db-data объем и может быть повторно использован в будущем. Монтаж связывания также можно использовать вместо названного тома здесь, но я предпочитаю названный том в таких сценариях.

Как получить доступ к журналам из контейнера в Docker

Для того, чтобы увидеть журналы из контейнера, вы можете использовать Контейнерные журналы команда. Общий синтаксис для команды выглядит следующим образом:

docker container logs 

Чтобы получить доступ к журналам из Notes-db Контейнер, вы можете выполнить следующую команду:

docker container logs notes-db

# The files belonging to this database system will be owned by user "postgres".
# This user must also own the server process.

# The database cluster will be initialized with locale "en_US.utf8".
# The default database encoding has accordingly been set to "UTF8".
# The default text search configuration will be set to "english".
#
# Data page checksums are disabled.
#
# fixing permissions on existing directory /var/lib/postgresql/data ... ok
# creating subdirectories ... ok
# selecting dynamic shared memory implementation ... posix
# selecting default max_connections ... 100
# selecting default shared_buffers ... 128MB
# selecting default time zone ... Etc/UTC
# creating configuration files ... ok
# running bootstrap script ... ok
# performing post-bootstrap initialization ... ok
# syncing data to disk ... ok
#
#
# Success. You can now start the database server using:
#
#     pg_ctl -D /var/lib/postgresql/data -l logfile start
#
# initdb: warning: enabling "trust" authentication for local connections
# You can change this by editing pg_hba.conf or using the option -A, or
# --auth-local and --auth-host, the next time you run initdb.
# waiting for server to start....2021-01-25 13:39:21.613 UTC [47] LOG:  starting PostgreSQL 12.5 (Debian 12.5-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
# 2021-01-25 13:39:21.621 UTC [47] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
# 2021-01-25 13:39:21.675 UTC [48] LOG:  database system was shut down at 2021-01-25 13:39:21 UTC
# 2021-01-25 13:39:21.685 UTC [47] LOG:  database system is ready to accept connections
#  done
# server started
# CREATE DATABASE
#
#
# /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
#
# 2021-01-25 13:39:22.008 UTC [47] LOG:  received fast shutdown request
# waiting for server to shut down....2021-01-25 13:39:22.015 UTC [47] LOG:  aborting any active transactions
# 2021-01-25 13:39:22.017 UTC [47] LOG:  background worker "logical replication launcher" (PID 54) exited with exit code 1
# 2021-01-25 13:39:22.017 UTC [49] LOG:  shutting down
# 2021-01-25 13:39:22.056 UTC [47] LOG:  database system is shut down
#  done
# server stopped
#
# PostgreSQL init process complete; ready for start up.
#
# 2021-01-25 13:39:22.135 UTC [1] LOG:  starting PostgreSQL 12.5 (Debian 12.5-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
# 2021-01-25 13:39:22.136 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
# 2021-01-25 13:39:22.136 UTC [1] LOG:  listening on IPv6 address "::", port 5432
# 2021-01-25 13:39:22.147 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
# 2021-01-25 13:39:22.177 UTC [75] LOG:  database system was shut down at 2021-01-25 13:39:22 UTC
# 2021-01-25 13:39:22.190 UTC [1] LOG:  database system is ready to accept connections

Очевидно по тексту в строке 57 база данных поднимается и готова принять соединения снаружи. Есть также --follow или -f Опция для команды, которая позволяет подключить консоль к выводу журналов и получить непрерывный поток текста.

Как создать сеть и прикрепление сервера базы данных в Docker

Как вы узнали в предыдущем разделе, контейнеры должны быть прикреплены к пользовательской сети мостовой сети, чтобы взаимодействовать друг с другом, используя имена контейнера. Для этого создайте сеть с именем Notes-API-сеть В вашей системе:

docker network create notes-api-network

Теперь прикрепите Notes-db Контейнер к этой сети, выполняя следующую команду:

docker network connect notes-api-network notes-db

Как написать DockerFile

Перейдите в каталог, в котором вы клонируете код проекта. Внутри там, иди внутрь Notes-API/API каталог и создать новый Dockerfile Отказ Поместите следующий код в файл:

# stage one
FROM node:lts-alpine as builder

# install dependencies for node-gyp
RUN apk add --no-cache python make g++

WORKDIR /app

COPY ./package.json .
RUN npm install --only=prod

# stage two
FROM node:lts-alpine

EXPOSE 3000
ENV NODE_ENV=production

USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app

COPY . .
COPY --from=builder /app/node_modules  /home/node/app/node_modules

CMD [ "node", "bin/www" ]

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

  • Этап 1 использует Узел: LTS-Alpine Как его база и использует строитель как сценическое имя.
  • В строке 5 мы устанавливаем Python , сделать и G ++ Отказ Узел-GYP Инструмент требует от этих трех пакетов для пробега.
  • На линии 7, мы устанавливаем /приложение каталог как Workdir Отказ
  • На строке 9 и 10 мы копируем Package.json Файл к Workdir И установите все зависимости.
  • Этап 2 также использует Узел-ЛТС: Alpine как база.
  • В строке 16 мы устанавливаем Node_env Переменная среды для Производство Отказ Это важно для API для правильной работы.
  • Из строки 18 до линии 20, мы устанавливаем пользователя по умолчанию на Узел Создайте /Home/Node/App каталог, и установите, что как Workdir Отказ
  • В строке 22 мы копируем все файлы проекта и в строке 23 мы копируем node_modules каталог из строитель сцена. Этот каталог содержит все встроенные зависимости, необходимые для запуска приложения.
  • В строке 25 мы устанавливаем команду по умолчанию.

Чтобы построить изображение из этого Dockerfile Вы можете выполнить следующую команду:

docker image build --tag notes-api .

# Sending build context to Docker daemon  37.38kB
# Step 1/14 : FROM node:lts-alpine as builder
#  ---> 471e8b4eb0b2
# Step 2/14 : RUN apk add --no-cache python make g++
#  ---> Running in 5f20a0ecc04b
# fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
# fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
# (1/21) Installing binutils (2.33.1-r0)
# (2/21) Installing gmp (6.1.2-r1)
# (3/21) Installing isl (0.18-r0)
# (4/21) Installing libgomp (9.3.0-r0)
# (5/21) Installing libatomic (9.3.0-r0)
# (6/21) Installing mpfr4 (4.0.2-r1)
# (7/21) Installing mpc1 (1.1.0-r1)
# (8/21) Installing gcc (9.3.0-r0)
# (9/21) Installing musl-dev (1.1.24-r3)
# (10/21) Installing libc-dev (0.7.2-r0)
# (11/21) Installing g++ (9.3.0-r0)
# (12/21) Installing make (4.2.1-r2)
# (13/21) Installing libbz2 (1.0.8-r1)
# (14/21) Installing expat (2.2.9-r1)
# (15/21) Installing libffi (3.2.1-r6)
# (16/21) Installing gdbm (1.13-r1)
# (17/21) Installing ncurses-terminfo-base (6.1_p20200118-r4)
# (18/21) Installing ncurses-libs (6.1_p20200118-r4)
# (19/21) Installing readline (8.0.1-r0)
# (20/21) Installing sqlite-libs (3.30.1-r2)
# (21/21) Installing python2 (2.7.18-r0)
# Executing busybox-1.31.1-r9.trigger
# OK: 212 MiB in 37 packages
# Removing intermediate container 5f20a0ecc04b
#  ---> 637ca797d709
# Step 3/14 : WORKDIR /app
#  ---> Running in 846361b57599
# Removing intermediate container 846361b57599
#  ---> 3d58a482896e
# Step 4/14 : COPY ./package.json .
#  ---> 11b387794039
# Step 5/14 : RUN npm install --only=prod
#  ---> Running in 2e27e33f935d
#  added 269 packages from 220 contributors and audited 1137 packages in 140.322s
#
# 4 packages are looking for funding
#   run `npm fund` for details
#
# found 0 vulnerabilities
#
# Removing intermediate container 2e27e33f935d
#  ---> eb7cb2cb0b20
# Step 6/14 : FROM node:lts-alpine
#  ---> 471e8b4eb0b2
# Step 7/14 : EXPOSE 3000
#  ---> Running in 4ea24f871747
# Removing intermediate container 4ea24f871747
#  ---> 1f0206f2f050
# Step 8/14 : ENV NODE_ENV=production
#  ---> Running in 5d40d6ac3b7e
# Removing intermediate container 5d40d6ac3b7e
#  ---> 31f62da17929
# Step 9/14 : USER node
#  ---> Running in 0963e1fb19a0
# Removing intermediate container 0963e1fb19a0
#  ---> 0f4045152b1c
# Step 10/14 : RUN mkdir -p /home/node/app
#  ---> Running in 0ac591b3adbd
# Removing intermediate container 0ac591b3adbd
#  ---> 5908373dfc75
# Step 11/14 : WORKDIR /home/node/app
#  ---> Running in 55253b62ff57
# Removing intermediate container 55253b62ff57
#  ---> 2883cdb7c77a
# Step 12/14 : COPY . .
#  ---> 8e60893a7142
# Step 13/14 : COPY --from=builder /app/node_modules  /home/node/app/node_modules
#  ---> 27a85faa4342
# Step 14/14 : CMD [ "node", "bin/www" ]
#  ---> Running in 349c8ca6dd3e
# Removing intermediate container 349c8ca6dd3e
#  ---> 9ea100571585
# Successfully built 9ea100571585
# Successfully tagged notes-api:latest

Перед запуском контейнера с помощью этого изображения убедитесь, что контейнер базы данных работает и подключен к Notes-API-сеть Отказ

docker container inspect notes-db

# [
#     {
#         ...
#         "State": {
#             "Status": "running",
#             "Running": true,
#             "Paused": false,
#             "Restarting": false,
#             "OOMKilled": false,
#             "Dead": false,
#             "Pid": 11521,
#             "ExitCode": 0,
#             "Error": "",
#             "StartedAt": "2021-01-26T06:55:44.928510218Z",
#             "FinishedAt": "2021-01-25T14:19:31.316854657Z"
#         },
#         ...
#         "Mounts": [
#             {
#                 "Type": "volume",
#                 "Name": "notes-db-data",
#                 "Source": "/var/lib/docker/volumes/notes-db-data/_data",
#                 "Destination": "/var/lib/postgresql/data",
#                 "Driver": "local",
#                 "Mode": "z",
#                 "RW": true,
#                 "Propagation": ""
#             }
#         ],
#         ...
#         "NetworkSettings": {
#             ...
#             "Networks": {
#                 "bridge": {
#                     "IPAMConfig": null,
#                     "Links": null,
#                     "Aliases": null,
#                     "NetworkID": "e4c7ce50a5a2a49672155ff498597db336ecc2e3bbb6ee8baeebcf9fcfa0e1ab",
#                     "EndpointID": "2a2587f8285fa020878dd38bdc630cdfca0d769f76fc143d1b554237ce907371",
#                     "Gateway": "172.17.0.1",
#                     "IPAddress": "172.17.0.2",
#                     "IPPrefixLen": 16,
#                     "IPv6Gateway": "",
#                     "GlobalIPv6Address": "",
#                     "GlobalIPv6PrefixLen": 0,
#                     "MacAddress": "02:42:ac:11:00:02",
#                     "DriverOpts": null
#                 },
#                 "notes-api-network": {
#                     "IPAMConfig": {},
#                     "Links": null,
#                     "Aliases": [
#                         "37755e86d627"
#                     ],
#                     "NetworkID": "06579ad9f93d59fc3866ac628ed258dfac2ed7bc1a9cd6fe6e67220b15d203ea",
#                     "EndpointID": "5b8f8718ec9a5ec53e7a13cce3cb540fdf3556fb34242362a8da4cc08d37223c",
#                     "Gateway": "172.18.0.1",
#                     "IPAddress": "172.18.0.2",
#                     "IPPrefixLen": 16,
#                     "IPv6Gateway": "",
#                     "GlobalIPv6Address": "",
#                     "GlobalIPv6PrefixLen": 0,
#                     "MacAddress": "02:42:ac:12:00:02",
#                     "DriverOpts": {}
#                 }
#             }
#         }
#     }
# ]

Я сократил вывод для удобного просмотра здесь. На мою систему Notes-db Контейнер работает, использует Notes-db-data Объем и прилагается к Notes-API-сеть мост.

Как только вы уверены, что все на месте, вы можете запустить новый контейнер, выполнив следующую команду:

docker container run \
    --detach \
    --name=notes-api \
    --env DB_HOST=notes-db \
    --env DB_DATABASE=notesdb \
    --env DB_PASSWORD=secret \
    --publish=3000:3000 \
    --network=notes-api-network \
    notes-api
    
# f9ece420872de99a060b954e3c236cbb1e23d468feffa7fed1e06985d99fb919

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

Notes-API Приложение требует трех изменений среды для установки. Они следующие:

  • Db_host – Это хост сервера базы данных. Учитывая, что оба сервера базы данных, так и API прикреплены к той же пользовательской сети мостовой сети, сервер базы данных может быть воздействием для использования своего имени контейнера, который является Notes-db в таком случае.
  • Db_database – База данных, которую эта API будет использовать. На Запуск сервера базы данных Мы устанавливаем имя базы данных по умолчанию для NotesDB используя Postgrees_db Переменная среды. Мы будем использовать это здесь.
  • Db_password – Пароль для подключения к базе данных. Это также было установлено на Запуск сервера базы данных подраздел, используя Postgres_password Переменная среды.

Чтобы проверить, работает ли контейнер правильно или нет, вы можете использовать Контейнер Ls . команда:

docker container ls

# CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                    NAMES
# f9ece420872d   notes-api     "docker-entrypoint.s…"   12 minutes ago   Up 12 minutes   0.0.0.0:3000->3000/tcp   notes-api
# 37755e86d627   postgres:12   "docker-entrypoint.s…"   17 hours ago     Up 14 minutes   5432/tcp                 notes-db

Контейнер работает сейчас. Вы можете посетить http://127.0.0.1:3000/ чтобы увидеть API в действии.

API имеет пять маршрутов всего, что вы можете видеть внутри /notes-api/api/api/routes/notes.js файл.

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

Как выполнить команды в запущенном контейнере

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

Для этого вам придется использовать exec Команда для выполнения пользовательской команды внутри бегового контейнера.

Общий синтаксис для exec Команда выглядит следующим образом:

docker container exec  

Выполнить NPM запустить дБ: мигрировать внутри Notes-API Контейнер, вы можете выполнить следующую команду:

docker container exec notes-api npm run db:migrate

# > notes-api@ db:migrate /home/node/app
# > knex migrate:latest
#
# Using environment: production
# Batch 1 run: 1 migrations

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

docker container exec -it notes-api sh

# / # uname -a
# Linux b5b1367d6b31 5.10.9-201.fc33.x86_64 #1 SMP Wed Jan 20 16:56:23 UTC 2021 x86_64 Linux

Как написать сценарии управления в Docker

Управление мульти-контейнером проектом наряду с сетью и томами и материалами означает, что написание много команд. Чтобы упростить процесс, у меня обычно есть помощь от простого Скрипты оболочки и а Makefile Отказ

Вы найдете четыре сценария оболочки в Notes-API каталог. Они следующие:

  • boot.sh – используется для запуска контейнеров, если они уже существуют.
  • build.sh – Создает и управляет контейнерами. Это также создает изображения, объемы и сети при необходимости.
  • уничтожить .SH – Удаляет все контейнеры, объемы и сети, связанные с этим проектом.
  • Стоп.ш – останавливает все беговые контейнеры.

Есть также Makefile который содержит четыре цели, названные Начать , Стоп , построить и уничтожить Каждый из них вызывает ранее упомянутые сценарии оболочки.

Если контейнер находится в запущенном состоянии в вашей системе, выполняя сделать остановку должен остановить все контейнеры. Выполнение сделать уничтожить Должен остановить контейнеры и удалить все. Убедитесь, что вы запускаете скрипты внутри Notes-API Каталог:

make destroy

# ./shutdown.sh
# stopping api container --->
# notes-api
# api container stopped --->

# stopping db container --->
# notes-db
# db container stopped --->

# shutdown script finished

# ./destroy.sh
# removing api container --->
# notes-api
# api container removed --->

# removing db container --->
# notes-db
# db container removed --->

# removing db data volume --->
# notes-db-data
# db data volume removed --->

# removing network --->
# notes-api-network
# network removed --->

# destroy script finished

Если вы получаете разрешение, запрещено ошибка, чем выполнять chmod + x На скриптах:

chmod +x boot.sh build.sh destroy.sh shutdown.sh

Я не собираюсь объяснить эти сценарии, потому что они просто Если-ж Заявления вместе с некоторыми командами Docker, которые вы уже видели много раз. Если у вас есть некоторое понимание оболочки Linux, вы также сможете понять сценарии.

Как составить проекты, используя docker-compose

В предыдущем разделе вы узнали о управлении многофункциональным проектом и трудностями. Вместо того, чтобы написать так много команд, есть более простым способом управления многофункциональными проектами, инструментом под названием Docker Compose Отказ

По словам докера Документация

Хотя составляют работу во всех средах, это более сосредоточено на разработке и тестировании. Использование композиции на производственной среде вообще не рекомендуется.

Docker Compose Основы

Перейдите в каталог, в котором вы клонировали репозиторий, пришли с этой книгой. Идите внутрь Notes-API/API каталог и создать Dockerfile.dev файл. Поместите следующий код в нем:

# stage one
FROM node:lts-alpine as builder

# install dependencies for node-gyp
RUN apk add --no-cache python make g++

WORKDIR /app

COPY ./package.json .
RUN npm install

# stage two
FROM node:lts-alpine

ENV NODE_ENV=development

USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app

COPY . .
COPY --from=builder /app/node_modules /home/node/app/node_modules

CMD [ "./node_modules/.bin/nodemon", "--config", "nodemon.json", "bin/www" ]

Код практически идентичен Dockerfile что вы работали в предыдущем разделе. Три различия в этом файле следующие:

  • В строке 10 мы бежим NPM установить вместо NPM запустить установку Потому что мы хотим также зависимости разработки.
  • На строке 15 мы устанавливаем Node_env Переменная среды для Развитие вместо Производство Отказ
  • В строке 24 мы используем инструмент под названием Номемон Чтобы получить функцию горячей перезагрузки для API.

Вы уже знаете, что у этого проекта есть две контейнеры:

  • Notes-db – сервер базы данных, работающий по PostgreSQL.
  • Notes-API – Остальное API Powered by Express.js

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

Так же, как Docker Daemon использует Dockerfile Для создания изображений Docker Compose использует Docker-Compose.yaml Файл для чтения определений службы от.

Голова до Notes-API каталог и создать новый Docker-Compose.yaml файл. Поместите следующий код в вновь созданный файл:

version: "3.8"

services: 
    db:
        image: postgres:12
        container_name: notes-db-dev
        volumes: 
            - notes-db-dev-data:/var/lib/postgresql/data
        environment:
            POSTGRES_DB: notesdb
            POSTGRES_PASSWORD: secret
    api:
        build:
            context: ./api
            dockerfile: Dockerfile.dev
        image: notes-api:dev
        container_name: notes-api-dev
        environment: 
            DB_HOST: db ## same as the database service name
            DB_DATABASE: notesdb
            DB_PASSWORD: secret
        volumes: 
            - /home/node/app/node_modules
            - ./api:/home/node/app
        ports: 
            - 3000:3000

volumes:
    notes-db-dev-data:
        name: notes-db-dev-data

Каждый действительный Docker-Compose.yaml Файл запускается, определяя версию файла. На момент написания, 3.8 это последняя версия. Вы можете посмотреть последнюю версию здесь Отказ

Блоки в файле yaml определяются отданием. Я пройду через каждую из блоков и объясню, что они делают.

  • Услуги Блок содержит определения для каждого из услуг или контейнеров в приложении. дБ и API являются двумя услугами, которые составляют этот проект.
  • дБ Блок определяет новую услугу в приложении и удерживает необходимую информацию для запуска контейнера. Каждый сервис требует либо предварительно построенного изображения, либо Dockerfile Для запуска контейнера. Для дБ Сервис Мы используем официальный образ PostgreSQL.
  • В отличие от дБ Сервис, предварительно построенное изображение для API Служба не существует. Итак, мы будем использовать Dockerfile.dev файл.
  • Объемы Блок определяет любое название объема, необходимое любым из услуг. В то время он только приключается только Notes-db-dev-data Объем, используемый дБ услуга.

Теперь, когда есть обзор высокого уровня Docker-Compose.yaml Файл, давайте посмотрим на отдельные услуги.

Код определения для дБ Сервис выглядит следующим образом:

db:
    image: postgres:12
    container_name: notes-db-dev
    volumes: 
        - db-data:/var/lib/postgresql/data
    environment:
        POSTGRES_DB: notesdb
        POSTGRES_PASSWORD: secret
  • изображение Клавиша содержит репозиторий изображения и тег, используемый для этого контейнера. Мы используем Postgres: 12 Изображение для запуска контейнера базы данных.
  • Container_Name Указывает имя контейнера. По умолчанию контейнеры называются следующими <Название каталога проекта> _ <имя обслуживания> синтаксис. Вы можете переопределить, что используя Container_Name Отказ
  • Объемы Массив содержит сопоставления громкости для обслуживания и поддержки с именованными томами, анонимными томами и креплениями связывания. Синтаксис <Источник>: <Пункт назначения> идентичен тому, что вы видели раньше.
  • окружающая среда Карта содержит значения различных переменных среды, необходимые для обслуживания.

Код определения для API Сервис выглядит следующим образом:

api:
    build:
        context: ./api
        dockerfile: Dockerfile.dev
    image: notes-api:dev
    container_name: notes-api-dev
    environment: 
        DB_HOST: db ## same as the database service name
        DB_DATABASE: notesdb
        DB_PASSWORD: secret
    volumes: 
        - /home/node/app/node_modules
        - ./api:/home/node/app
    ports: 
        - 3000:3000
  • API Сервис не приходит с предварительно построенным изображением. Вместо этого он имеет конфигурацию сборки. Под построить Блок. Мы определяем контекст и имя DockerFile для создания изображения. Теперь у вас должно быть понимание контекста и докера, поэтому я не буду тратить время, объясняя их.
  • изображение Ключ содержит имя изображения, которое будет построен. Если не назначен, изображение будет названо после <Название каталога проекта> _ <имя обслуживания> синтаксис.
  • Внутри окружающая среда карта, Db_host Переменная демонстрирует особенность композиции. То есть вы можете обратиться к другой службе в том же приложении, используя его имя. Итак, дБ Здесь будет заменен IP-адрес API Сервисный контейнер. Db_database и Db_password Переменные должны совпадать с Postgrees_db и Postgres_password соответственно от дБ Определение обслуживания.
  • В Объемы Карта, вы можете увидеть анонимный том и описанный привязка. Синтаксис идентичен тому, что вы видели в предыдущих разделах.
  • Порты Карта определяет любое отображение порта. Синтаксис, : <Контейнерный порт> идентичен --publish Вариант вы использовали ранее.

Наконец, код для Объемы составляет:

volumes:
    db-data:
        name: notes-db-dev-data

Любой именованный объем, используемый в любом из услуг, должен быть определен здесь. Если вы не определите имя, объем будет назван после <Название каталога проекта> _ И ключ вот DB-Data Отказ

Вы можете узнать о различных вариантах для конфигурации громкости в официальном Документы Отказ

Как начать сервисы в Docker Compose

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

Прежде чем вы выполнять команду, убедитесь, что вы открыли свой терминал в том же каталоге, где Docker-Compose.yaml Файл есть. Это очень важно для каждого Docker-Compose Команда вы выполняете.

docker-compose --file docker-compose.yaml up --detach

# Creating network "notes-api_default" with the default driver
# Creating volume "notes-db-dev-data" with default driver
# Building api
# Sending build context to Docker daemon  37.38kB
#
# Step 1/13 : FROM node:lts-alpine as builder
#  ---> 471e8b4eb0b2
# Step 2/13 : RUN apk add --no-cache python make g++
#  ---> Running in 197056ec1964
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container 197056ec1964
#  ---> 6609935fe50b
# Step 3/13 : WORKDIR /app
#  ---> Running in 17010f65c5e7
# Removing intermediate container 17010f65c5e7
#  ---> b10d12e676ad
# Step 4/13 : COPY ./package.json .
#  ---> 600d31d9362e
# Step 5/13 : RUN npm install
#  ---> Running in a14afc8c0743
### LONG INSTALLATION STUFF GOES HERE ###
#  Removing intermediate container a14afc8c0743
#  ---> 952d5d86e361
# Step 6/13 : FROM node:lts-alpine
#  ---> 471e8b4eb0b2
# Step 7/13 : ENV NODE_ENV=development
#  ---> Running in 0d5376a9e78a
# Removing intermediate container 0d5376a9e78a
#  ---> 910c081ce5f5
# Step 8/13 : USER node
#  ---> Running in cfaefceb1eff
# Removing intermediate container cfaefceb1eff
#  ---> 1480176a1058
# Step 9/13 : RUN mkdir -p /home/node/app
#  ---> Running in 3ae30e6fb8b8
# Removing intermediate container 3ae30e6fb8b8
#  ---> c391cee4b92c
# Step 10/13 : WORKDIR /home/node/app
#  ---> Running in 6aa27f6b50c1
# Removing intermediate container 6aa27f6b50c1
#  ---> 761a7435dbca
# Step 11/13 : COPY . .
#  ---> b5d5c5bdf3a6
# Step 12/13 : COPY --from=builder /app/node_modules /home/node/app/node_modules
#  ---> 9e1a19960420
# Step 13/13 : CMD [ "./node_modules/.bin/nodemon", "--config", "nodemon.json", "bin/www" ]
#  ---> Running in 5bdd62236994
# Removing intermediate container 5bdd62236994
#  ---> 548e178f1386
# Successfully built 548e178f1386
# Successfully tagged notes-api:dev
# Creating notes-api-dev ... done
# Creating notes-db-dev  ... done

--detach или -d Опция здесь функционирует так же, как тот, который вы видели раньше. --file или -f Вариант необходим только если файл yaml не назван Docker-Compose.yaml (Но я использовал здесь для демонстрационных целей).

Кроме того вверх Команда есть Начать команда. Основное отличие этих двух в том, что Начать Команда не создает отсутствующих контейнеров, только начинает существующие контейнеры. Это в основном так же, как Старт контейнера команда.

--build Вариант для вверх Команда заставляет восстановить изображения. Есть некоторые другие варианты для вверх Команда, которую вы можете увидеть в официальном Документы Отказ

Как перечислить услуги в Docker Compose

Хотя контейнеры обслуживания, созданные COMPOPE, могут быть перечислены с использованием Контейнер Ls . Команда, есть PS Команда для листинга контейнеров, определенных только в YAML.

docker-compose ps

#     Name                   Command               State           Ports         
# -------------------------------------------------------------------------------
# notes-api-dev   docker-entrypoint.sh ./nod ...   Up      0.0.0.0:3000->3000/tcp
# notes-db-dev    docker-entrypoint.sh postgres    Up      5432/tcp

Это не как информативно, как Контейнер Ls . Вывод, но это полезно, когда у вас есть тонны контейнеров, работающих одновременно.

Как выполнить команды внутри беговой службы в Docker Compose

Я надеюсь, что вы помните с предыдущего раздела, который вы должны запустить несколько сценариев миграции для создания таблиц базы данных для этого API.

Так же, как Контейнер Exec Команда, есть exec Команда для Docker-Compose Отказ Общий синтаксис для команды выглядит следующим образом:

docker-compose exec  

Для выполнения NPM запустить дБ: мигрировать Команда внутри API Сервис, вы можете выполнить следующую команду:

docker-compose exec api npm run db:migrate

# > notes-api@ db:migrate /home/node/app
# > knex migrate:latest
# 
# Using environment: development
# Batch 1 run: 1 migrations

В отличие от Контейнер Exec Команда, вам не нужно проходить -итайте Флаг для интерактивных сессий. Docker-Compose Это автоматически.

Как получить доступ к журналам из беговой службы в Docker Compose

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

docker-compose logs 

Чтобы получить доступ к журналам из API Сервис, выполните следующую команду:

docker-compose logs api

# Attaching to notes-api-dev
# notes-api-dev | [nodemon] 2.0.7
# notes-api-dev | [nodemon] reading config ./nodemon.json
# notes-api-dev | [nodemon] to restart at any time, enter `rs`
# notes-api-dev | [nodemon] or send SIGHUP to 1 to restart
# notes-api-dev | [nodemon] ignoring: *.test.js
# notes-api-dev | [nodemon] watching path(s): *.*
# notes-api-dev | [nodemon] watching extensions: js,mjs,json
# notes-api-dev | [nodemon] starting `node bin/www`
# notes-api-dev | [nodemon] forking
# notes-api-dev | [nodemon] child pid: 19
# notes-api-dev | [nodemon] watching 18 files
# notes-api-dev | app running -> http://127.0.0.1:3000

Это просто часть от вывода журнала. Вы можете вроде крюк в выходной поток службы и получить журналы в режиме реального времени, используя -f или --follow вариант. Любой более поздний журнал появится мгновенно в терминале, если вы не выходите, нажав Ctrl + C или закрывая окно. Контейнер будет продолжать работать, даже если вы выходите из окна журнала.

Как остановить услуги в Docker Compose

Чтобы остановить услуги, есть два подхода, которые вы можете взять. Первый – это вниз команда. вниз Команда останавливает все контейнеры и удаляет их из системы. Это также удаляет любые сети:

docker-compose down --volumes

# Stopping notes-api-dev ... done
# Stopping notes-db-dev  ... done
# Removing notes-api-dev ... done
# Removing notes-db-dev  ... done
# Removing network notes-api_default
# Removing volume notes-db-dev-data

--Волумы Опция указывает, что вы хотите удалить любые именованные объема (ы), определенные в Объемы блокировать. Вы можете узнать о дополнительных вариантах для вниз команда в официальном Документы Отказ

Другая команда для остановки услуг – Стоп команда, которая функционирует идентично для Контейнер Стоп команда. Он останавливает все контейнеры для приложения и сохраняет их. Эти контейнеры могут быть начаты с Начать или вверх команда.

Как составить приложение полнотека в Docker Compose

В этом подсечении мы будем добавлять интерфейс для наших API наших заметок и превратив его в полное приложение для полного стека. Я не буду объяснять ни одного из Dockerfile.dev Файлы в этом подразделе (кроме одного для услуги nginx Service), поскольку они идентичны некоторым другим остальным, которые вы уже видели в предыдущих подразделах.

Если вы клонировали репозиторий кода проекта, затем идите внутрь FullStack-Notes-приложение каталог. Каждый каталог внутри корня проекта содержит код для каждого сервиса и соответствующую Dockerfile Отказ

Прежде чем начать с Docker-Compose.yaml Файл Давайте посмотрим на диаграмму, как приложение будет работать:

Вместо того, чтобы принимать запросы непосредственно, как и ранее, в данном приложении все запросы будут впервые получены NGINX (давайте назовем его маршрутизатора).

Маршрутизатор будет посмотреть, имеет ли запрошенную конечную точку /API в этом. Если да, маршрутизатор будет направлять запрос на заднев или, если нет, маршрутизатор будет направлять запрос на передний план.

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

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

Я не буду войти в конфигурацию Nginx здесь. Эта тема рода из-за объема этой книги. Но если вы хотите посмотреть на него, продолжайте и проверьте /notes-api/nginx/development.conf и /notes-api/nginx/broduction.conf файлы. Код для /notes-api/nginx/Dockerfile.dev составляет:

FROM nginx:stable-alpine

COPY ./development.conf /etc/nginx/conf.d/default.conf

Все это делает, это скопируйте файл конфигурации на /etc/nginx/Conf.d/default.conf внутри контейнера.

Давайте начнем написать Docker-Compose.yaml файл. Помимо API и дБ Услуги будут клиент и nginx Сервисы. Также будут определены определения сети, которые я буду вскоре.

version: "3.8"

services: 
    db:
        image: postgres:12
        container_name: notes-db-dev
        volumes: 
            - db-data:/var/lib/postgresql/data
        environment:
            POSTGRES_DB: notesdb
            POSTGRES_PASSWORD: secret
        networks:
            - backend
    api:
        build: 
            context: ./api
            dockerfile: Dockerfile.dev
        image: notes-api:dev
        container_name: notes-api-dev
        volumes: 
            - /home/node/app/node_modules
            - ./api:/home/node/app
        environment: 
            DB_HOST: db ## same as the database service name
            DB_PORT: 5432
            DB_USER: postgres
            DB_DATABASE: notesdb
            DB_PASSWORD: secret
        networks:
            - backend
    client:
        build:
            context: ./client
            dockerfile: Dockerfile.dev
        image: notes-client:dev
        container_name: notes-client-dev
        volumes: 
            - /home/node/app/node_modules
            - ./client:/home/node/app
        networks:
            - frontend
    nginx:
        build:
            context: ./nginx
            dockerfile: Dockerfile.dev
        image: notes-router:dev
        container_name: notes-router-dev
        restart: unless-stopped
        ports: 
            - 8080:80
        networks:
            - backend
            - frontend

volumes:
    db-data:
        name: notes-db-dev-data

networks: 
    frontend:
        name: fullstack-notes-application-network-frontend
        driver: bridge
    backend:
        name: fullstack-notes-application-network-backend
        driver: bridge

Файл практически идентичен предыдущему, с которым вы работали. Единственное, что нужно, – это конфигурация сети. Код для сети Блок выглядит следующим образом:

networks: 
    frontend:
        name: fullstack-notes-application-network-frontend
        driver: bridge
    backend:
        name: fullstack-notes-application-network-backend
        driver: bridge

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

Я также добавил сети Блок в каждом из определений обслуживания. Таким образом, то API и дБ Сервис будет прикреплен к одной сети и клиент Сервис будет прикреплен к отдельной сети. Но nginx Сервис будет прикреплен как к сетям, чтобы он мог выполнять как маршрутизатор между передними и задними сервисами.

Начните все услуги, выполнив следующую команду:

docker-compose --file docker-compose.yaml up --detach

# Creating network "fullstack-notes-application-network-backend" with driver "bridge"
# Creating network "fullstack-notes-application-network-frontend" with driver "bridge"
# Creating volume "notes-db-dev-data" with default driver
# Building api
# Sending build context to Docker daemon  37.38kB
# 
# Step 1/13 : FROM node:lts-alpine as builder
#  ---> 471e8b4eb0b2
# Step 2/13 : RUN apk add --no-cache python make g++
#  ---> Running in 8a4485388fd3
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container 8a4485388fd3
#  ---> 47fb1ab07cc0
# Step 3/13 : WORKDIR /app
#  ---> Running in bc76cc41f1da
# Removing intermediate container bc76cc41f1da
#  ---> 8c03fdb920f9
# Step 4/13 : COPY ./package.json .
#  ---> a1d5715db999
# Step 5/13 : RUN npm install
#  ---> Running in fabd33cc0986
### LONG INSTALLATION STUFF GOES HERE ###
# Removing intermediate container fabd33cc0986
#  ---> e09913debbd1
# Step 6/13 : FROM node:lts-alpine
#  ---> 471e8b4eb0b2
# Step 7/13 : ENV NODE_ENV=development
#  ---> Using cache
#  ---> b7c12361b3e5
# Step 8/13 : USER node
#  ---> Using cache
#  ---> f5ac66ca07a4
# Step 9/13 : RUN mkdir -p /home/node/app
#  ---> Using cache
#  ---> 60094b9a6183
# Step 10/13 : WORKDIR /home/node/app
#  ---> Using cache
#  ---> 316a252e6e3e
# Step 11/13 : COPY . .
#  ---> Using cache
#  ---> 3a083622b753
# Step 12/13 : COPY --from=builder /app/node_modules /home/node/app/node_modules
#  ---> Using cache
#  ---> 707979b3371c
# Step 13/13 : CMD [ "./node_modules/.bin/nodemon", "--config", "nodemon.json", "bin/www" ]
#  ---> Using cache
#  ---> f2da08a5f59b
# Successfully built f2da08a5f59b
# Successfully tagged notes-api:dev
# Building client
# Sending build context to Docker daemon  43.01kB
# 
# Step 1/7 : FROM node:lts-alpine
#  ---> 471e8b4eb0b2
# Step 2/7 : USER node
#  ---> Using cache
#  ---> 4be5fb31f862
# Step 3/7 : RUN mkdir -p /home/node/app
#  ---> Using cache
#  ---> 1fefc7412723
# Step 4/7 : WORKDIR /home/node/app
#  ---> Using cache
#  ---> d1470d878aa7
# Step 5/7 : COPY ./package.json .
#  ---> Using cache
#  ---> bbcc49475077
# Step 6/7 : RUN npm install
#  ---> Using cache
#  ---> 860a4a2af447
# Step 7/7 : CMD [ "npm", "run", "serve" ]
#  ---> Using cache
#  ---> 11db51d5bee7
# Successfully built 11db51d5bee7
# Successfully tagged notes-client:dev
# Building nginx
# Sending build context to Docker daemon   5.12kB
# 
# Step 1/2 : FROM nginx:stable-alpine
#  ---> f2343e2e2507
# Step 2/2 : COPY ./development.conf /etc/nginx/conf.d/default.conf
#  ---> Using cache
#  ---> 02a55d005a98
# Successfully built 02a55d005a98
# Successfully tagged notes-router:dev
# Creating notes-client-dev ... done
# Creating notes-api-dev    ... done
# Creating notes-router-dev ... done
# Creating notes-db-dev     ... done

Теперь посетите http://localhost: 8080 И VUILà!

Попробуйте добавить и удалять заметки, чтобы посмотреть, работает ли приложение правильно. Проект также поставляется с Shell Scripts и A Makefile Отказ Исследуйте их, чтобы увидеть, как вы можете запустить этот проект без помощи Docker-Compose Как вы сделали в предыдущем разделе.

Заключение

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

Помимо этого, я написал по всей длине справочники на других сложных темах, доступных бесплатно на FreeCodeCamp.

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

Если вы наслаждались моим письмом и хотите, чтобы меня мотивированы, подумайте о том, чтобы уйти начать на Github и одобрить меня за соответствующие навыки на LinkedIn Отказ Я также принимаю спонсорство, чтобы вы могли рассмотреть Покупая мне кофе если вы хотите.

Я всегда открыт для предложений и дискуссий на Количество платформ Отказ Следуй за мной на Twitter или LinkedIn И ударил меня прямыми сообщениями.

В конце концов, подумайте об использовании ресурсов с другими, потому что

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