Docker

Содержание

#1. Сборка;
#2. Запуск контейнеров;
#3. Отладка контейнеров;
#4  О Docker в AWS ECS;
#5. Очистка образов Docker;
#6. Извлечение образов Docker из удалённого регистра;
#7. Экспорт и импорт физических образов Docker.

Вступление

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

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

Менее удачливые из нас не имеют стабильных сред с идеальными CI/CD процессами. Эта статья как раз для тех, кто попадает в эту категорию. Содержащаяся в ней информация взята из реального опыта. Как и вы, я проводил за отладкой дни напролёт. Эта же статья является своеобразным дополнением основного сайта технической документации Docker. В то же время она заостряет внимание на самых распространённых командах, которые вы будете использовать ежедневно в процессе работы с Docker.

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

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

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

Сборка Docker

$ docker build \
--build-arg ARTIFACTORY_USERNAME=timothy.mugayi \
--build-arg ARTIFACTORY_SECRET_TOKEN=AP284233QnYX9Ckrdr7pUEY1F \
--build-arg LICENSE_URL='https://source.com/license.txt' \
--no-cache  -t helloworld:latest.

Это создаст образ Docker с опциональными аргументами сборки. Docker будет по умолчанию кэшировать результаты для первой сборки Dockerfile или последующих сборок, основанных на слоях, добавленных к образу через команду run в Dockerfile, что позволит этим сборкам работать быстрее. Если вам это не нужно, можете добавить аргумент “no-cache”, как это сделано в примере выше.

Заметка: команды Docker могут быть выполнены по имени или по ID контейнера. <CONTAINER> допускает подстановку либо ID контейнера, либо его имени.

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

$ docker start <CONTAINER>

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

$ docker stop <CONTAINER>

Остановка существующего контейнера Docker.

$ docker stop $(docker container ls -aq)

Если у вас есть несколько запущенных контейнеров Docker, и вы хотите остановить их все, наберите docker stop и список ID этих контейнеров.

$ docker exec -ti <CONTAINER> [COMMAND]

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

$ docker run -ti — image <IMAGE> <CONTAINER> [COMMAND]

Существует чёткое различие между Docker run и start. run по сути делает две вещи: 1) создаёт новый контейнер образа и 2) выполняет этот контейнер. Если вам когда-нибудь понадобится повторно запустить давший сбой или совершивших выход контейнер, используйте команду docker start.

$ docker run -ti — rm — image <IMAGE> <CONTAINER> [COMMAND]

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

docker run -d  <IMAGE>:<IMAGE_TAG>

Usage: 
   docker run -d  helloworld:latest

Если вы хотите запустить команду docker run в отдельном состоянии — например, в качестве демона (фоновый процесс) в Linux, то можете добавить -d к этой команде(ам) run.

$ docker pause <CONTAINER>

Приостановить все запущенные процессы внутри конкретного контейнера. 

$ docker ps -a

Эта команды выводит список всех образов Docker, запущенных ранее. Как только вы определили образ, который нужно запустить, выполните команду, приведённую ниже. Убедитесь, что изменили ID контейнера, чтобы он отображал результаты, показанные изначальной командой docker ps -a.

$ sudo docker run {container ID} -e AWS_DEFAULT_REGION=us-east-1 \
e INPUT_QUEUE_URL="https://sqs.us-east-1.amazonaws.com/my_input_sqs_queue.fifo" \
e REDIS_ENDPOINT="redis.dfasdf.0001.cache.amazonaws.com:8000" \
e ENV=dev \
e DJANGO_SETTINGS_MODULE=engine.settings \
e REDIS_HOST="cmgadsfv7avlq.us-east-1.redis.amazonaws.com" \
e REDIS_PORT=5439 \
e REDIS_USER=hello \
e REDIS_PASSWORD=trasdf**#0ynpXkzg

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

$ docker run -p <host_public_port>:<container_port>

Если вам когда-нибудь придётся раскрывать порты Docker, то имейте в виду, что для проброса портов команда запуска получает аргумент -p. Там, где host_public_port — это порт вашей машины, вам нужно, чтобы Docker переадресовал container_port. Для дополнительных портов также добавляйте аргументы -p.

$ docker run -p <host_public_port1>:<container_port1> -p <host_public_port2>:<container_port2>

Отладка контейнеров Docker

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

$ docker history <IMAGE> 

example usage:

$ docker history my_image_name

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

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

Если у вас есть директива from, run и/или copy в Dockerfile и затем вы build этот образ, то благодаря этой директиве run будет создан один слой со своим собственным ID образа. Этот образ/слой затем покажется в docker history с этим ID образа и датой его создания. Последующие директивы продолжат генерацию аналогичных записей. При этом колонка CREATED BY будет приблизительно соответствовать строке в Dockerfile, как это показано на следующем изображении:

Отображение команды “docker history”.
$ docker images

Список всех образов, хранящихся в данный момент на машине.

$ docker inspect <IMAGE|CONTAINER ID>

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

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

  • ID контейнера и временную метку его создания.
  • Текущий статус (полезен при выяснении, остановлен ли контейнер и, если остановлен, то почему).
  • Информация образа Docker, информация о привязках к файловой системе и томе, а также о подключениях.
  • Переменные среды — например, параметры командной строки, переданные в контейнер.
  • Конфигурация сети: IP адрес и шлюз, а также второстепенные адреса для IPv4 и IPv6.
$ docker version

Отображение версии Docker, включая версию клиента и сервера, установленные на машине в данный момент.

Да, вы всё правильно поняли. Docker — это клиент-серверное приложение. Демон (продолжительно выполняемая фоновая служба Linux) — это сервер, а CLI — это один из многих клиентов. Демон Docker раскрывает REST API, посредством которого с ним могут взаимодействовать различные инструменты.

$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:34 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:29:19 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
Устройство архитектуры клиент-сервер.

Docker в AWS ECS

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

Используйте команду docker exec -it <container ID> /bin/bash для получения доступа к оболочке, если вам понадобится найти образ Docker, проваливший запуск, например, если вы используете кластер AWS ECS и получаете неточное сообщение об ошибке, подобное приведённому ниже.

Честно говоря, причиной тому может быть многое, включая: 1) проблемы кода, например, было выброшено не перехваченное исключение, и контейнер Docker не запустился, 2) вам не хватает пространства на жёстком диске, если вы используете кластер ECS в экземплярах EC2 и при этом для размещения ECS не используете Fargate, 3) ваш действующий контейнер Docker исчерпал доступную EC2 память.

Essential container in task exited

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

$ sudo docker ps -a --filter status=dead --filter status=exited --last 1

Если сомневаетесь, перезапустите службу Docker

$ sudo service docker stop$ sudo service docker start# on a MAC you an use the docker utilty or alternatively run $ killall Docker && open /Applications/Docker.app

Здесь пояснения не требуются.

Очистка образов Docker

$ docker system prune

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

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

docker kill <CONTAINER>

Убить выполняющийся контейнер.

$ docker kill $(docker ps -q)

Убить все выполняющиеся контейнеры.

$ docker rm <CONTAINER>

Удалить конкретный контейнер, не запущенный в данный момент. Если образ существует в удалённом реестре, он не будет затронут.

$ docker rm $(docker ps -a -q):

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

$ docker logs my_container

Получить доступ к журналам контейнера (полезно при отладке).

Загрузка образов Docker из удалённого реестра

Docker Hub

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

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

$ docker run --rm -p 8787:8787 rocker/verse

Docker сперва проверит, доступен ли этот образ на вашей локальной машине. Если нет, он приступит к его загрузке с репозитория Docker Hub. Такое поведение предусмотрено изначально.

$ docker pull rocker/verse

Если вы хотите просто извлечь образ и не запускать контейнер, тогда подойдёт команда docker pull.

docker login --username={DOCKERHUB_USERNNAME} --email={DOCKERHUB_EMAIL}

Для входа на Docker Hub вы можете запустить вышеприведённую команду, которая предложит ввести пароль.

Пользовательский реестр Docker

$ docker login your.docker.host.com
Username: foo
Password: ********
Email: [email protected]

Если вы извлекаете образ из обобщённого пользовательского реестра Docker, требующего авторизацию, то команда docker login позволят произвести извлечение из любого реестра Docker, как показано выше. Имейте в виду, что при использовании приведённого подхода, будет создана запись в файле ~/.docker/config.json. Присоедините ~/.docker/config.json для изменения деталей авторизации.

Реестр Elastic-контейнеров Amazon

Реестр Elastic-контейнеров (ECS) —  это полноценно поддерживаемый реестр контейнеров Docker, позволяющий разработчикам хранить, поддерживать и разворачивать образы контейнеров Docker. Amazon ECS отлично работает с Amazon ECR. Если вам вдруг понадобится извлечь образы из реестра ECR, следуйте следующим инструкциям.

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

Amazon ECR требует, чтобы ключи пользователя IAM имели разрешения (ecr:GetAuthrizationToken) через политику IAM, только тогда вы сможете авторизоваться и извлечь образы. В качестве альтернативы вы можете использовать утилиту Amazon ECR Docker Credential Helper. Ниже представлен подход, предполагающий использование вами AWS CLI и корректную настройку всех разрешений.

$ aws ecr list-images --repository-name=twitter-data-engine-core$ aws ecr describe-images -- repository-name=twitter-data-engine-core$ aws ecr get-login -- region us-east-1 -- no-include-email

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

$ docker login -u AWS -p {YOUR_TEMPORARY_TOKEN}$ docker pull 723123836077.dkr.ecr.us-east-1.amazonaws.com/twitter-data-engine-core:build-9

Экспорт и импорт физических образов Docker

$ docker save your_docker_image:latest > /usr/local/your_docker_image.tar$ docker load < /usr/local/your_docker_image.tar

Если вам понадобится экспортировать образ Docker на диск и загрузить обратно, вышеуказанная команда это осуществит.

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

Всех вам благ и удачного кодинга!

Читайте также:


Перевод статьи Timothy Mugayi: The Ultimate Docker Command List.