Advertisement
  1. Code
  2. DevOps

Докер с нуля: работа с контейнерами, часть 1

Scroll to top
Read Time: 8 min
This post is part of a series called Docker from the Ground Up: Working with Containers.
Docker From the Ground Up: Working With Containers, Part 2

() translation by (you can also view the original English article)

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

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

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

Прежде чем начать, убедитесь, что Docker в вашей среде установлен правильно. В зависимости от того, как он установлен, и вашего пользователя, вам может потребоваться запустить его под sudo. Я пропущу sudo.

Запуск обораза

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

1
FROM scratch
2
COPY hello /
3
CMD ["/hello"]

Команда просто запускает двоичный файл «hello», который был скопирован в корень контейнера при создании образа.

Foreground vs. Detached

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

Запуск контейнера «Без названия»

Самый простой способ запуска контейнера: docker run <image id or name>.

Когда вы запускаете контейнер с помощью этой команды, Docker назначает ему имя, состоящее из двух случайных слов. Например: docker run hello-world.

Если у вас уже есть образ hello-world, то Docker запустит его. Если такого образа нет, он вытащит его из официального Docker-хранилища DockerHub, а затем запустит его. Результат должен выглядеть так:

1
Hello from Docker!
2
This message shows that your installation appears to be working correctly.
3
4
To generate this message, Docker took the following steps:
5
 1. The Docker client contacted the Docker daemon.
6
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
7
 3. The Docker daemon created a new container from that image which runs the
8
    executable that produces the output you are currently reading.
9
 4. The Docker daemon streamed that output to the Docker client, which sent it
10
    to your terminal.
11
12
To try something more ambitious, you can run an Ubuntu container with:
13
 $ docker run -it ubuntu bash
14
15
Share images, automate work-flows, and more with a free Docker ID:
16
 https://cloud.docker.com/
17
18
For more examples and ideas, visit:
19
 https://docs.docker.com/engine/userguide/

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

1
docker ps -a  --format "table {{.ID}}\t{{.Status}}\t{{.Names}}"
2
3
CONTAINER ID        STATUS                     NAMES
4
8e2e491accb5        Exited (0) 2 minutes ago   clever_liskov

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

Запуск именованного контейнера

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

Docker позволяет вам называть свои контейнеры, когда вы запускаете их, предоставляя аргумент командной строки «--name <имя контейнера>». В простых случаях, когда у вас есть только один контейнер на образ, вы можете назвать контейнер по имени вашего образа: docker run --name hello-world hello-world.

Теперь, если мы посмотрим на процесс (я удалил clever_liskov ранее), мы увидим, что контейнер называется hello-world:

1
docker ps -a --format "table {{.ID}}\t{{.Names}}"
2
CONTAINER ID        NAMES
3
f6fe77b3b6e8        hello-world

Существует несколько преимуществ для именованного контейнера:

  • У вас есть стабильное имя для ваших контейнеров, которые вы используете как в интерактивном режиме, так и в сценариях.
  • Вы можете выбрать значащее имя.
  • Вы можете выбрать краткое имя для удобства при работе в интерактивном режиме.
  • Это предотвращает случайное наличие нескольких контейнеров одного и того же образа (при условии, что вы всегда указываете одно и то же имя).

Давайте посмотрим на последний вариант. Если я попытаюсь снова запустить ту же команду запуска с тем же именем «hello-world», я получаю сообщение об ошибке:

1
docker run --name hello-world hello-world
2
docker: Error response from daemon: Conflict. The container name
3
"/hello-world" is already in use by container 
4
f6fe77b3b6e8e77ccf346c32c599e67b2982893ca39f0415472c2949cacc4a51. 
5
You have to remove (or rename) that container to be able to reuse 
6
that name.
7
See 'docker run --help'.

Запуск автоматического удаления образа

По умолчанию контейнеры придерживаются. Иногда они вам не нужны. Вместо того, чтобы вручную удалять выведенные контейнеры, вы можете это автоматизировать. Аргумент командной строки --rm сделает что нужно: docker run --rm hello-world.

Запуск другой команды

По умолчанию Docker запускает команду, указанную в Dockerfile , который используется для сборки образа (или непосредственно в точке входа, если команда не найдена). Вы всегда можете переопределить ее, предоставив свою собственную команду в конце команды run. Давайте запустим ls -la на образе busybox (образ hello-world не имеет исполняемого файла ls):

1
docker run busybox ls -la
2
total 44
3
drwxr-xr-x   18 root     root          4096 Mar 18 17:06 .
4
drwxr-xr-x   18 root     root          4096 Mar 18 17:06 ..
5
-rwxr-xr-x    1 root     root             0 Mar 18 17:06 .dockerenv
6
drwxr-xr-x    2 root     root         12288 Mar  9 00:05 bin
7
drwxr-xr-x    5 root     root           340 Mar 18 17:06 dev
8
drwxr-xr-x    2 root     root          4096 Mar 18 17:06 etc
9
drwxr-xr-x    2 nobody   nogroup       4096 Mar  9 00:05 home
10
dr-xr-xr-x   85 root     root             0 Mar 18 17:06 proc
11
drwxr-xr-x    2 root     root          4096 Mar  9 00:05 root
12
dr-xr-xr-x   13 root     root             0 Mar 18 17:06 sys
13
drwxrwxrwt    2 root     root          4096 Mar  9 00:05 tmp
14
drwxr-xr-x    3 root     root          4096 Mar  9 00:05 usr
15
drwxr-xr-x    4 root     root          4096 Mar  9 00:05 var

Взаимодействие с хостом

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

Передача переменных среды в контейнер

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

1
docker run --rm -it -e ENV_FROM_HOST="123" busybox
2
/ # env
3
HOSTNAME=8e7672bce5a7
4
SHLVL=1
5
HOME=/root
6
ENV_FROM_HOST=123
7
TERM=xterm
8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
9
PWD=/
10
/ #

Первая строка запускает контейнер busybox, передавая ему переменную ENV_FROM_HOST, а затем внутри контейнера, команда env, показывает, что ENV_FROM_HOST установлена правильно.

Вы также можете использовать переменные среды хоста. Это устанавливает пару переменных среды хоста и использует их в команде запуска:

1
$ export VAR_1=1
2
$ export VAR_2=2
3
$ docker run --rm -it -e VAR_1="$VAR_1" -e VAR_2="$VAR_2" busybox

Внутри контейнера они теперь видны:

1
/ # env | grep VAR
2
VAR_1=1
3
VAR_2=2

Монтаж каталогов хоста

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

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

Здесь я создаю файл на хосте: $ echo "Yeah, it works!" > ~/data/1.txt

Затем я запускаю образ busybox, устанавливая каталог ~/data в /data в контейнере и отображая содержимое файла на экране:

1
$ docker run --rm -v ~/data:/data busybox cat /data/1.txt
2
Yeah, it works!

Я использовал здесь команду cat /data/1.txt.

Предоставление портов хосту

Если вы выставляете порт в Dockerfile с помощью EXPOSE, он будет доступен только для других контейнеров докера. Чтобы сделать его доступным на хосте, вам нужно использовать аргумент командной строки -p. Синтаксис следующий: -p <host port>: <открытый порт контейнера>.

Здесь выполняется образ nginx, который предоставляет порт 80 и использует аргумент командной строки -p, чтобы сделать его видимым на хосте на порте 9000:

1
docker run --name nginx --rm -d -p 9000:80 nginx

Обратите внимание: в отличие от предыдущих команд, выполнявших некоторые задачи и завершенных, контейнер nginx будет продолжать работать и слушать входящие запросы. Давайте проверим, действительно ли nginx работает и отвечает на запросы на порт 9000. Я предпочитаю отличный HTTP-клиент httpie вместо curl для проверки веб-серверов и служб из командной строки:

1
http HEAD localhost:9000
2
3
HTTP/1.1 200 OK
4
Accept-Ranges: bytes
5
Connection: keep-alive
6
Content-Length: 612
7
Content-Type: text/html
8
Date: Sun, 19 Mar 2017 07:35:55 GMT
9
ETag: "58a323e4-264"
10
Last-Modified: Tue, 14 Feb 2017 15:36:04 GMT
11
Server: nginx/1.11.10

Вывод

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

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

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.