Создание собственных образов

Docker образы являются основой контейнеров. Каждый раз, когда мы используем docker run мы указываем какой образ использовать. В предыдущих разделах вы использовали уже существовавшие образы Docker, к примеру образ ubuntu и training/webapp.

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

В этом уроке мы исследуем образы Docker более подробно:

  • Управление и работа с образами на локально на хосте Docker.
  • Создание базовых образов.
  • Загрузка образов в реестр Docker Hub.

Список образов на хосте

Давайте начнем со списка образов которые присутствуют на хосте. Вы можете посмотреть список выполнив команду docker images:

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               1d073211c498        3 days ago          187.9 MB
busybox             latest              2c5ac3f849df        5 days ago          1.113 MB
training/webapp     latest              54bb4e8718e8        5 months ago        348.7 MB

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

  • Из какого репозитория образ, к примеру ubuntu.
  • Версия каждого образа, например 14.04.
  • Уникальный ID каждого образа.

Совет: Вы можете использовать инструмент от стороннего производителя dockviz или Image layers site для отображения визуализации данных изображения.

Репозиторий может хранить разные версии образа. В случае с ubuntu есть много вариантов Ubuntu 10.04, 12.04, 12.10, 13.04, 13.10 и 14.04. Каждый вариант обозначен тегом и вы можете выбрать нужный вам:

ubuntu:14.04

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

$ docker run -t -i ubuntu:14.04 /bin/bash

Если вместо этого вы хотите запустить образ Ubuntu 12.04, выполните команду:

$ docker run -t -i ubuntu:12.04 /bin/bash

Если вы не указали вариант, например, вы просто используете ubuntu, то Докер будет по умолчанию использовать образ ubuntu:latest.

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

Загрузка нового образа

Итак, как же получить новый образ? Docker автоматически скачает любой образ который вы используете, но которого еще нет на вашем Docker хосте. Но это может увеличить время запуска контейнера. Если вы хотите заранее загрузить образ, вы можете сделать это командой docker pull. Предположим, вы хотите скачать образ centos.

$ docker pull centos

Using default tag: latest
latest: Pulling from library/centos
f1b10cd84249: Pull complete
c852f6d61e65: Pull complete
7322fbe74aa5: Pull complete
Digest: sha256:90305c9112250c7e3746425477f1c4ef112b03b4abe78c612e092037bfecc3b7
Status: Downloaded newer image for centos:latest

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

$ docker run -t -i centos /bin/bash

bash-4.1#

Поиск образов

Одной из особенностей Docker является то что множество людей создают собственные образы для различных целей. Многие из них загружают их на Docker Hub. Вы можете искать эти образы на веб-сайте Docker Hub.

indexsearch

Вы также можете искать образы используя команду docker search. Предположим, нашей команде нужны образы Ruby и Sinatra для разработки веб-приложения. Вы можете произвести поиск подходящего образа использовав команду docker search для поиска всех образов содержащих слово sinatra.

$ docker search sinatra
NAME                                   DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
training/sinatra                       Sinatra training image                          0                    [OK]
marceldegraaf/sinatra                  Sinatra test app                                0
mattwarren/docker-sinatra-demo                                                         0                    [OK]
luisbebop/docker-sinatra-hello-world                                                   0                    [OK]
bmorearty/handson-sinatra              handson-ruby + Sinatra for Hands on with D...   0
subwiz/sinatra                                                                         0
bmorearty/sinatra                                                                      0
. . .

Вы можете видеть что команда вернула много образов со словом sinatra. В списке с результатами есть название, описание, рейтинг (который отражает социальную популярность образа), а также статус официальности автобилда. Официальные репозитории тщательно модерируються компанией Docker. Автоматические репозитории позволяют вам проверить источник и содержание образа.

вы просмотрели доступные образы и решили использовать образ training/sinatra. До сих пор вы сталкивались с двумя типами репозиториев. Первый тип: образы вроде ubuntu, которые называются базовыми или корневыми. Базовые образы поставляются компанией Docker, они проверены и поддерживаются. Их легко узнать по названиям из одного слова.

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

Загрузка (pull) образа

Вы выбрали образ training/sinatra, и теперь можете скачать его командой docker pull.

$ docker pull training/sinatra

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

$ docker run -t -i training/sinatra /bin/bash

root@a8cb6ce02d85:/#

Создание собственных образов

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

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

Обновление и коммит образа

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

$ docker run -t -i training/sinatra /bin/bash

root@0b2616b0e5a8:/#

Примечание: Скопируйте ID созданного контейнера 0b2616b0e5a8 (у вас он может отличаться), он скоро вам понадобится.

Сперва давайте обновим Ruby внутри нашего контейнера:

root@0b2616b0e5a8:/# apt-get install -y ruby2.0-dev

Теперь добавим json гем.

root@0b2616b0e5a8:/# gem2.0 install json

Когда все сделано можно выйти из контейнера командой exit.

Теперь у вас есть модифицированный контейнер. Вы можете сделать коммит контейнера в образ командой docker commit.

$ docker commit -m "Added json gem" -a "Kate Smith" \
0b2616b0e5a8 ouruser/sinatra:v2

4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c

Вы использовали команду docker commit. при этом бало добавлено два флага: -m и -a. Флаг -m по аналогии с git (или другими системами контроля версий) позволяет добавить к коммиту комментарий. Флаг -a дает возможность указать автора обновления.

Вы также указали контейнер из которого хотите создать новый образ, 0b2616b0e5a8 (скопированный ранее ID контейнера) и название с версией для нового образа:

ouruser/sinatra:v2

Разберем название ouruser/sinatra:v2 более подробно. Оно содержит имя пользователя ouruser, который создает образ. Далее идет само имя образа, здесь мы оставили имя оригинала без изменений sinatra. В самом конце указывается тег (версия): v2.

Теперь можно посмотреть на новый образ ouruser/sinatra выполнив команду docker images.

$ docker images

REPOSITORY          TAG     IMAGE ID       CREATED       SIZE
training/sinatra    latest  5bc342fa0b91   10 hours ago  446.7 MB
ouruser/sinatra     v2      3c59e02ddd1a   10 hours ago  446.7 MB
ouruser/sinatra     latest  5db5f8471261   10 hours ago  446.7 MB

Используем новый образ для создания контейнера:

$ docker run -t -i ouruser/sinatra:v2 /bin/bash

root@78e82f680994:/#

Построение образа из Dockerfile

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

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

Сначала, создайте папку и Dockerfile.

$ mkdir sinatra

$ cd sinatra

$ touch Dockerfile

Если вы используете Docker Machine на Windows, вы можете попасть в директорию хоста командой cd /c/Users/your_user_name.

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

# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get update && apt-get install -y ruby ruby-dev
RUN gem install sinatra

Посмотрим что делает файл Dockerfile. Каждая инструкция состоит из префикса и команды.

INSTRUCTION statement

Примечание: Используйте # что бы оставлять комментарии

Первая инструкция FROM указывает Docker какой образ будет базовым, в данном случае им будет Ubuntu 14.04. С помощью инструкции MAINTAINER можно указать автора поддерживающего образ.

И наконец, вы использовали две инструкции RUN, которые выполняют команду внутри образа, к примеру устанавливают пакет. Здесь мы обновляем наш APT кэш и устанавливаем Ruby, RubyGems и затем Sinatra гем.

Теперь, давайте возьмем наш Dockerfile и используем команду docker build для создания образа.

$ docker build -t ouruser/sinatra:v2 .

Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon
Step 1 : FROM ubuntu:14.04
 ---> e54ca5efa2e9
Step 2 : MAINTAINER Kate Smith <ksmith@example.com>
 ---> Using cache
 ---> 851baf55332b
Step 3 : RUN apt-get update && apt-get install -y ruby ruby-dev
 ---> Running in 3a2558904e9b
Selecting previously unselected package libasan0:amd64.
(Reading database ... 11518 files and directories currently installed.)
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libasan0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libatomic1:amd64.
Preparing to unpack .../libatomic1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libatomic1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libgmp10:amd64.
Preparing to unpack .../libgmp10_2%3a5.1.3+dfsg-1ubuntu1_amd64.deb ...
Unpacking libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...
Selecting previously unselected package libisl10:amd64.
Preparing to unpack .../libisl10_0.12.2-1_amd64.deb ...
Unpacking libisl10:amd64 (0.12.2-1) ...
Selecting previously unselected package libcloog-isl4:amd64.
Preparing to unpack .../libcloog-isl4_0.18.2-1_amd64.deb ...
Unpacking libcloog-isl4:amd64 (0.18.2-1) ...
Selecting previously unselected package libgomp1:amd64.
Preparing to unpack .../libgomp1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libgomp1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libitm1:amd64.
Preparing to unpack .../libitm1_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libitm1:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libmpfr4:amd64.
Preparing to unpack .../libmpfr4_3.1.2-1_amd64.deb ...
Unpacking libmpfr4:amd64 (3.1.2-1) ...
Selecting previously unselected package libquadmath0:amd64.
Preparing to unpack .../libquadmath0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libquadmath0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libtsan0:amd64.
Preparing to unpack .../libtsan0_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libtsan0:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package libyaml-0-2:amd64.
Preparing to unpack .../libyaml-0-2_0.1.4-3ubuntu3_amd64.deb ...
Unpacking libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...
Selecting previously unselected package libmpc3:amd64.
Preparing to unpack .../libmpc3_1.0.1-1ubuntu1_amd64.deb ...
Unpacking libmpc3:amd64 (1.0.1-1ubuntu1) ...
Selecting previously unselected package openssl.
Preparing to unpack .../openssl_1.0.1f-1ubuntu2.4_amd64.deb ...
Unpacking openssl (1.0.1f-1ubuntu2.4) ...
Selecting previously unselected package ca-certificates.
Preparing to unpack .../ca-certificates_20130906ubuntu2_all.deb ...
Unpacking ca-certificates (20130906ubuntu2) ...
Selecting previously unselected package manpages.
Preparing to unpack .../manpages_3.54-1ubuntu1_all.deb ...
Unpacking manpages (3.54-1ubuntu1) ...
Selecting previously unselected package binutils.
Preparing to unpack .../binutils_2.24-5ubuntu3_amd64.deb ...
Unpacking binutils (2.24-5ubuntu3) ...
Selecting previously unselected package cpp-4.8.
Preparing to unpack .../cpp-4.8_4.8.2-19ubuntu1_amd64.deb ...
Unpacking cpp-4.8 (4.8.2-19ubuntu1) ...
Selecting previously unselected package cpp.
Preparing to unpack .../cpp_4%3a4.8.2-1ubuntu6_amd64.deb ...
Unpacking cpp (4:4.8.2-1ubuntu6) ...
Selecting previously unselected package libgcc-4.8-dev:amd64.
Preparing to unpack .../libgcc-4.8-dev_4.8.2-19ubuntu1_amd64.deb ...
Unpacking libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...
Selecting previously unselected package gcc-4.8.
Preparing to unpack .../gcc-4.8_4.8.2-19ubuntu1_amd64.deb ...
Unpacking gcc-4.8 (4.8.2-19ubuntu1) ...
Selecting previously unselected package gcc.
Preparing to unpack .../gcc_4%3a4.8.2-1ubuntu6_amd64.deb ...
Unpacking gcc (4:4.8.2-1ubuntu6) ...
Selecting previously unselected package libc-dev-bin.
Preparing to unpack .../libc-dev-bin_2.19-0ubuntu6_amd64.deb ...
Unpacking libc-dev-bin (2.19-0ubuntu6) ...
Selecting previously unselected package linux-libc-dev:amd64.
Preparing to unpack .../linux-libc-dev_3.13.0-30.55_amd64.deb ...
Unpacking linux-libc-dev:amd64 (3.13.0-30.55) ...
Selecting previously unselected package libc6-dev:amd64.
Preparing to unpack .../libc6-dev_2.19-0ubuntu6_amd64.deb ...
Unpacking libc6-dev:amd64 (2.19-0ubuntu6) ...
Selecting previously unselected package ruby.
Preparing to unpack .../ruby_1%3a1.9.3.4_all.deb ...
Unpacking ruby (1:1.9.3.4) ...
Selecting previously unselected package ruby1.9.1.
Preparing to unpack .../ruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package libruby1.9.1.
Preparing to unpack .../libruby1.9.1_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking libruby1.9.1 (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package manpages-dev.
Preparing to unpack .../manpages-dev_3.54-1ubuntu1_all.deb ...
Unpacking manpages-dev (3.54-1ubuntu1) ...
Selecting previously unselected package ruby1.9.1-dev.
Preparing to unpack .../ruby1.9.1-dev_1.9.3.484-2ubuntu1_amd64.deb ...
Unpacking ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...
Selecting previously unselected package ruby-dev.
Preparing to unpack .../ruby-dev_1%3a1.9.3.4_all.deb ...
Unpacking ruby-dev (1:1.9.3.4) ...
Setting up libasan0:amd64 (4.8.2-19ubuntu1) ...
Setting up libatomic1:amd64 (4.8.2-19ubuntu1) ...
Setting up libgmp10:amd64 (2:5.1.3+dfsg-1ubuntu1) ...
Setting up libisl10:amd64 (0.12.2-1) ...
Setting up libcloog-isl4:amd64 (0.18.2-1) ...
Setting up libgomp1:amd64 (4.8.2-19ubuntu1) ...
Setting up libitm1:amd64 (4.8.2-19ubuntu1) ...
Setting up libmpfr4:amd64 (3.1.2-1) ...
Setting up libquadmath0:amd64 (4.8.2-19ubuntu1) ...
Setting up libtsan0:amd64 (4.8.2-19ubuntu1) ...
Setting up libyaml-0-2:amd64 (0.1.4-3ubuntu3) ...
Setting up libmpc3:amd64 (1.0.1-1ubuntu1) ...
Setting up openssl (1.0.1f-1ubuntu2.4) ...
Setting up ca-certificates (20130906ubuntu2) ...
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
Setting up manpages (3.54-1ubuntu1) ...
Setting up binutils (2.24-5ubuntu3) ...
Setting up cpp-4.8 (4.8.2-19ubuntu1) ...
Setting up cpp (4:4.8.2-1ubuntu6) ...
Setting up libgcc-4.8-dev:amd64 (4.8.2-19ubuntu1) ...
Setting up gcc-4.8 (4.8.2-19ubuntu1) ...
Setting up gcc (4:4.8.2-1ubuntu6) ...
Setting up libc-dev-bin (2.19-0ubuntu6) ...
Setting up linux-libc-dev:amd64 (3.13.0-30.55) ...
Setting up libc6-dev:amd64 (2.19-0ubuntu6) ...
Setting up manpages-dev (3.54-1ubuntu1) ...
Setting up libruby1.9.1 (1.9.3.484-2ubuntu1) ...
Setting up ruby1.9.1-dev (1.9.3.484-2ubuntu1) ...
Setting up ruby-dev (1:1.9.3.4) ...
Setting up ruby (1:1.9.3.4) ...
Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6) ...
Processing triggers for ca-certificates (20130906ubuntu2) ...
Updating certificates in /etc/ssl/certs... 164 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
 ---> c55c31703134
Removing intermediate container 3a2558904e9b
Step 4 : RUN gem install sinatra
 ---> Running in 6b81cb6313e5
unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping
unable to convert "\xC3" to UTF-8 in conversion from ASCII-8BIT to UTF-8 to US-ASCII for README.rdoc, skipping
Successfully installed rack-1.5.2
Successfully installed tilt-1.4.1
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.5
4 gems installed
Installing ri documentation for rack-1.5.2...
Installing ri documentation for tilt-1.4.1...
Installing ri documentation for rack-protection-1.5.3...
Installing ri documentation for sinatra-1.4.5...
Installing RDoc documentation for rack-1.5.2...
Installing RDoc documentation for tilt-1.4.1...
Installing RDoc documentation for rack-protection-1.5.3...
Installing RDoc documentation for sinatra-1.4.5...
 ---> 97feabe5d2ed
Removing intermediate container 6b81cb6313e5
Successfully built 97feabe5d2ed

В команде docker build был использован флаг -t для указания принадлежности образа пользователю ouruser, имя репозитория sinatra и тега (версии) v2.

Вы также указываете расположение Dockerfile используя . поскольку Dockerfile находится в текущем каталоге.

Примечание: Вы также можете указать путь к файлу Dockerfile.

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

Далее вы можете увидеть как каждая инструкция Dockerfile выполняется шаг за шагом. Обратите внимание что при каждом шаге создается новый контейнер,следующая инструкция выполняется внутри контейнера и затем делается коммит изменений, аналогично команде docker commit которую мы недавно изучили. Когда все инструкции выполнены процедура завершается и выводится ID образа 97feabe5d2ed (с полным именем ouruser/sinatra:v2) а все промежуточные контейнеры удаляются.

Примечание: Образ не может иметь более 127 слоев, независимо от хранилища. Это ограничение устанавливается на глобальном уровне, чтобы стимулировать оптимизацию общего размера образов.

Теперь вы можете создать контейнер из нового образа.

$ docker run -t -i ouruser/sinatra:v2 /bin/bash

root@8196968dac35:/#

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

Установка тегов для образа

Вы также можете добавить тег к уже существующему образу после коммита и сборки. Для этого используйте команду docker tag. Теперь добавьте новый тег для образа ouruser/sinatra.

$ docker tag 5db5f8471261 ouruser/sinatra:devel

Команда docker tag принимает ID образа, в нашем случае 5db5f8471261, имя пользователя, имя репозитория и новый тег.

Посмотрим на новый тег нашего образа выполнив команду docker images.

$ docker images ouruser/sinatra

REPOSITORY          TAG     IMAGE ID      CREATED        SIZE
ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB

Дайджест образа

Образы использующие формат версии 2 или старше имеют контентно-адресный идентификатор называемый дайджест (digest). До тех пор пока вводные данные для генерации образа не изменны значение дайджеста тоже остаеться прежним. Таким образом дайджест можно считать хешем инструкций для построения образа. Для отображения образов и их дайджестов используйте флаг --digests:

$ docker images --digests | head

REPOSITORY        TAG      DIGEST                                                                     IMAGE ID      CREATED       SIZE
ouruser/sinatra   latest   sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf    5db5f8471261  11 hours ago  446.7 MB

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

$ docker pull ouruser/sinatra@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf

Вы можете использовать дайджест в командах create, run и rmi, также как в инструкции FROM для Dockerfile.

Выгрузка (push) образа на Docker Hub

После того, как вы создали новый образ вы можете запушить (push) его на Docker Hub с помощью команды docker push. Это позволяет вам поделиться им с другими, либо публично, либо разместить его в приватный репозиторий.

$ docker push ouruser/sinatra

The push refers to a repository [ouruser/sinatra] (len: 1)
Sending image list
Pushing repository ouruser/sinatra (3 tags)
. . .

Удаление образа с хоста

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

Удалите образ training/sinatra он больше вам не понадобится.

$ docker rmi training/sinatra

Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0

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

Следующие шаги

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

Перейдите в раздел Сетевые контейнеры.


Комментарии:

Комментариев нет, желаете стать первым?

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