Создание и запуск Docker контейнеров: пошаговая инструкция с примерами.

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

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

Создание и запуск контейнера

Пример 1: Явное скачивание образа и запуск контейнера

Допустим, вы хотите запустить в контейнере веб-сервер NGINX. Сначала вручную, с помощью pull, скачиваем образ:

[root@waky ~]# docker pull nginx
Using default tag: latest
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@waky ~]# systemctl start docker
[root@waky ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
38513bd72563: Pull complete
10d18f46ee87: Pull complete
a8d825a0683a: Pull complete
a131bc1d4bd5: Pull complete
3818929ac19f: Pull complete
1498b1cfda15: Pull complete
c50c84d0ed4d: Pull complete
Digest: sha256:029d4461bd98f124e531380505ceea2072418fdf28752aa73b7b273ba3048903
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@waky ~]#

Эта команда ищет образ nginx в локальной системе. Если он там есть, Docker использует его. Если нет — автоматически скачает его из Docker Hub и сохранит у вас локально. Если не указывать версию образа будет скачан последний (latest).

Затем запускаете контейнер командой run:

[root@waky ~]# docker run -d --name nginx_container -p 8080:80 nginx
398af1888e7dc4717f55a744235b0a86f0e3e4866c8db43020d77075ef104f23
[root@waky ~]#

Использованные параметры запуска:

d, —detach – запуск контейнера в фоновом режиме
name – имя контейнера
p, —publish list – привязка портов контейнера к портам хоста, в данном случае 80 порт контейнера к 8080 сервера, на котором работает Docker

Docker находит образ nginx в локальном хранилище и создает из него контейнер. На вывод подается ID созданного контейнера.

Мы можем проверить работу контейнера с помощью curl, обратимся к 8080 порту сервера, на который транслируется 80 (дефолтный) порт на котором работает веб сервер NGINX в контейнере.

[root@waky ~]# curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@waky ~]#

В ответ получили приветственную страницу NGINX.

Это классический сценарий: сначала pull, затем run.

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

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

У нас еще нет образа alpine, но мы сразу используем run:

[root@waky ~]# docker run -it --name alpine_shell alpine /bin/sh
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
2d35ebdb57d9: Pull complete
Digest: sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412
Status: Downloaded newer image for alpine:latest
/ # 

Использованные параметры запуска:

i, —interactive – держит STDIN контейнера открытым
t, —tty – дает доступ до псевдо терминала
name – имя контейнера

Docker ищет образ alpine у себя. Не находит и автоматически скачивает с Docker Hub, сохраняя его локально. После этого запускает контейнер, и выполняет переданную команду – /bin/sh. В итоге мы оказываемся в интерактивной оболочке внутри контейнера.

Для проверки выполним простейшую команду и выйдем из этой консоли:

/ # ping -c 3 google.com
PING google.com (74.125.131.113): 56 data bytes
64 bytes from 74.125.131.113: seq=0 ttl=105 time=121.833 ms
64 bytes from 74.125.131.113: seq=1 ttl=105 time=122.183 ms
64 bytes from 74.125.131.113: seq=2 ttl=105 time=122.364 ms
--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 121.833/122.126/122.364 ms
/ # exit
[root@waky ~]#

Управление контейнерами

После запуска контейнера, важно уметь управлять ими:

Команда Описание
docker psПросмотр запущенных контейнеров
docker ps -aПросмотр всех контейнеров (в т.ч. остановленных)
docker stop <имя/ID>Остановка контейнера
docker start <имя/ID>Запуск остановленного контейнера
docker restart <имя/ID>Перезапуск контейнера
docker rm <имя/ID>Удаление остановленного контейнера
docker imagesПросмотр скачанных образов
docker rmiУдаление образа

Просмотр запущенных контейнеров

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

[root@waky ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
398af1888e7d   nginx     "/docker-entrypoint.…"   50 minutes ago   Up 50 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx_container
[root@waky ~]#

Мы видим только один контейнер nginx_container, так как alpine_shell завершил свою работу после выхода из консоли.

Просмотр всех контейнеров

Для вывода всех контейнеров, в том числе и остановленных, используется аргумент -a:

[root@waky ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS                                     NAMES
31085b7910c5   alpine    "/bin/sh"                22 minutes ago   Exited (0) 18 minutes ago                                             alpine_shell
398af1888e7d   nginx     "/docker-entrypoint.…"   50 minutes ago   Up 50 minutes               0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx_container
[root@waky ~]#

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

Остановка контейнера

Работая с отдельными контейнерами можно использовать как их идентификатор (ID)так и имя (имена контейнеров уникальны).

Чтобы остановить контейнер используйте stop:

[root@waky ~]# docker stop nginx_container
nginx_container
[root@waky ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@waky ~]#

Список работающих контейнеров пуст.

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

С помощью start запустим обратно этот же контейнер, но вместо имени используем ID:

[root@waky ~]# docker start 398af1888e7d
398af1888e7d
[root@waky ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS         PORTS                                     NAMES
398af1888e7d   nginx     "/docker-entrypoint.…"   4 hours ago   Up 5 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx_container
[root@waky ~]#

Наш контейнер снова в списке активных.

Перезапуск контейнера

При необходимости перезапустить контейнер используется команда restart:

[root@waky ~]# docker restart nginx_container
nginx_container
[root@waky ~]#

Удаление остановленного контейнера

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

[root@waky ~]# docker rm alpine_shell
alpine_shell
[root@waky ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS         PORTS                                     NAMES
398af1888e7d   nginx     "/docker-entrypoint.…"   4 hours ago   Up 8 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx_container
[root@waky ~]#

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

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

[root@waky ~]# docker rm nginx_container
Error response from daemon: cannot remove container "nginx_container": container is running: stop the container before removing or force remove
[root@waky ~]# docker stop nginx_container
nginx_container
[root@waky ~]# docker rm nginx_container
nginx_container
[root@waky ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@waky ~]#

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

Просмотр скачанных образов

Осталось разобраться с образами. Получим список локальных образов:

[root@waky ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
alpine        latest    706db57fb206   2 weeks ago    8.32MB
nginx         latest    657fdcd1c365   2 weeks ago    152MB
[root@waky ~]#

Удаление образа

Удалим оставшиеся образы командой rmi:

[root@waky ~]# docker rmi alpine nginx
Untagged: alpine:latest
Untagged: alpine@sha256:4b7ce07002c69e8f3d704a9c5d6fd3053be500b7f1c69fc0d80990c2ad8dd412
Deleted: sha256:706db57fb2063f39f69632c5b5c9c439633fda35110e65587c5d85553fd1cc38
Deleted: sha256:256f393e029fa2063d8c93720da36a74a032bed3355a2bc3e313ad12f8bde9d1
Untagged: nginx:latest
Untagged: nginx@sha256:029d4461bd98f124e531380505ceea2072418fdf28752aa73b7b273ba3048903
Deleted: sha256:657fdcd1c3659cf57cfaa13f40842e0a26b49ec9654d48fdefee9fc8259b4aab
Deleted: sha256:80a172d7673c2438064e08c7891798ae736b9f65b24b33ee849aa519d660d0be
Deleted: sha256:d0437576e6e1ca87b75c0fc237b8afc322ddfb3ae0327a177503571a2f4bb20c
Deleted: sha256:eb5bda0607e6f7ae16c240a351645078a0249891a3a44d0d6a9ac41d55e2b446
Deleted: sha256:4ab1e8afb5f1c3249d9d243e1b4cd6abcedd20cd16693893852e97c1fc3a97f4
Deleted: sha256:0b7735a9234f3aff06db222061ecc411841f3b82ad205d3166618ea9fbf0ae80
Deleted: sha256:5ba3270e2400d2ade941f6ffe0e69696b3b47261239347f2fea5b74a39508a07
Deleted: sha256:d7c97cb6f1fe7cae982649e9f55efe201212e8acaa64bd668c083b204e4efd4c
[root@waky ~]# docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
[root@waky ~]#

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

Заключение

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