Статьи

10 практических советов по Docker для повседневного использования Docker

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

1. Несколько докеров на одном хосте.

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

Например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
# start a docker daemon and bind to a specific port
docker daemon -H tcp://$IP:5000 --storage-opt dm.fs=xfs \
            -p "/var/run/docker1.pid" \
            -g "/var/lib/docker1" \
            --exec-root="/var/run/docker1
  
# and start another daemon
docker daemon -H tcp://$IP:5001 --storage-opt dm.fs=xfs \
        -s devicemapper \
        --storage-opt dm.thinpooldev=/dev/mapper/docker--vg-docker--pool \
        -p "/var/run/docker2.pid" \
        -g "/var/lib/docker2" --exec-root="/var/run/docker2"
        --cluster-store=consul://$IP:8500 \
        --cluster-advertise=$IP:2376

2. Докер Exec конечно

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

Мы много работаем с cassandra, и проверяем, содержат ли таблицы правильные данные, или если вы просто хотите выполнить быстрый CQL-запрос, docker exec прекрасно работает:

01
02
03
04
05
06
07
08
09
10
$ docker ps --format "table {{.ID}}\t {{.Names}}\t {{.Status}}"
CONTAINER ID        NAMES               STATUS
682f47f97fce         cassandra           Up 2 minutes
4c45aea49180         consul              Up 2 minutes
  
$ docker exec -ti 682f47f97fce cqlsh --color
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 2.2.3 | CQL spec 3.3.1 | Native protocol v4]
Use HELP for help.
cqlsh>

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

1
2
3
4
5
6
7
8
9
$ docker exec -ti 682f47f97fce nodetool status
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address         Load       Tokens       Owns    Host ID                               Rack
UN  192.168.99.100  443.34 KB  256          ?       8f9f4a9c-5c4d-4453-b64b-7e01676361ff  rack1
  
Note: Non-system keyspaces don't have the same replication settings, effective ownership information is meaningless

И это, конечно, можно применить к любому (клиентскому) инструменту, связанному с изображением. Лично мне это гораздо проще, чем устанавливать все клиентские библиотеки локально и постоянно обновлять версии.

3. Докер проверяет и JQ

Это не столько совет по докеру, сколько совет по jq. Если вы не слышали о jq, это отличный инструмент для анализа JSON из командной строки. Это также делает его отличным инструментом для просмотра того, что происходит в контейнере, вместо того, чтобы использовать спецификатор –format, который я никогда не могу вспомнить, как именно использовать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Get network information:
$ docker inspect 4c45aea49180 | jq '.[].NetworkSettings.Networks'
{
  "bridge": {
    "EndpointID": "ba1b6efba16de99f260e0fa8892fd4685dbe2f79cba37ac0114195e9fad66075",
    "Gateway": "172.17.0.1",
    "IPAddress": "172.17.0.2",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:ac:11:00:02"
  }
}
  
# Get the arguments with which the container was started
$ docker inspect 4c45aea49180 | jq '.[].Args'
[
  "-server",
  "-advertise",
  "192.168.99.100",
  "-bootstrap-expect",
  "1"
]
  
# Get all the mounted volumes
11:22 $ docker inspect 4c45aea49180 | jq '.[].Mounts'
[
  {
    "Name": "a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f",
    "Source": "/mnt/sda1/var/lib/docker/volumes/a8125ffdf6c4be1db4464345ba36b0417a18aaa3a025267596e292249ca4391f/_data",
    "Destination": "/data",
    "Driver": "local",
    "Mode": "",
    "RW": true
  }
]

И, конечно же, также отлично подходит для запросов к другим видам (docker-esque) API, которые генерируют JSON (например, Marathon, Mesos, Consul и т. Д.). JQ предоставляет очень обширный API для доступа и обработки JSON. Более подробную информацию можно найти здесь: https://stedolan.github.io/jq/

4. Расширение существующего контейнера и отправка его в локальный реестр.

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

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

1
2
3
4
5
6
FROM progrium/consul
  
USER root
  
ADD bin/jq /bin/jq
ADD scripts/health-check.sh /bin/health-check.sh

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

1
2
3
4
$ docker build .
...
$ docker tag a3157e9edc18 <local-registry>/consul-local:some-tag
$ docker push <local-registry>/consul-local:some-tag

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

5. Доступ к докерам на удаленных хостах

Докер CLI — очень крутой инструмент. Одной из замечательных особенностей является то, что вы можете использовать его для легкого доступа к нескольким демонам Docker, даже если они находятся на разных хостах. Все, что вам нужно сделать, это установить переменную окружения DOCKER_HOST так, чтобы она указывала на адрес прослушивания демона docker, и, если порт, конечно, доступен, вы можете напрямую управлять докером на удаленном хосте. Это почти тот же принцип, который используется в docker-machine, когда вы запускаете docker-демон и настраиваете окружение через docker-machine env:

1
2
3
4
5
$ docker-machine env demo
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/jos/.docker/machine/machines/demo"
export DOCKER_MACHINE_NAME="demo"

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

6. Простота монтирования хост-каталогов

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

01
02
03
04
05
06
07
08
09
10
11
$ mkdir /Users/jos/temp/samplevolume/
$ ls /Users/jos/temp/samplevolume/
$ docker run -v /Users/jos/temp/samplevolume/:/samplevolume  -it --rm busybox
$ docker run -v /Users/jos/temp/samplevolume/:/samplevolume  -it --rm busybox
/ # ls samplevolume/
/ # touch samplevolume/hello
/ # ls samplevolume/
hello
/ # exit
$ ls /Users/jos/temp/samplevolume/
hello

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

1
2
3
4
5
6
7
8
9
$ docker inspect 76465cee5d49 | jq '.[].Mounts'
[
  {
    "Source": "/Users/jos/temp/samplevolume",
    "Destination": "/samplevolume",
    "Mode": "",
    "RW": true
  }
]

Есть ряд дополнительных функций, которые очень хорошо объяснены на сайте докера: https://docs.docker.com/engine/userguide/dockervolumes/

7. Добавьте разрешение DNS в ваши контейнеры.

Я уже упоминал, что мы используем консул для наших контейнеров. Consul — это распределенный магазин KV, который также обеспечивает обнаружение служб и проверку работоспособности. Для обнаружения службы Консул предоставляет либо REST API, либо старый добрый DNS. Самое замечательное в том, что вы можете указать DNS-сервер для своих контейнеров при запуске определенного образа. Поэтому, когда у вас запущен Консул (или любой другой DNS-сервер), вы можете добавить его в свой демон Docker следующим образом:

1
docker run -d --dns $IP_CONSUL --dns-search service.consul <rest of confguration>

Теперь мы можем разрешить IP-адрес любого контейнера, зарегистрированного в Консуле, по имени. Например, в нашей среде у нас есть кластер кассандры. Каждый экземпляр кассандры регистрируется под именем «кассандра» в нашем кластере консулов. Круто то, что теперь мы можем просто разрешить адрес cassandra на основе имени хоста (без необходимости использовать ссылки Docker).

1
2
3
4
5
6
7
8
9
$ docker exec -ti 00c22e9e7c4e bash
daemon@00c22e9e7c4e:/opt/docker$ ping cassandra
PING cassandra.service.consul (192.168.99.100): 56 data bytes
64 bytes from 192.168.99.100: icmp_seq=0 ttl=64 time=0.053 ms
64 bytes from 192.168.99.100: icmp_seq=1 ttl=64 time=0.077 ms
^C--- cassandra.service.consul ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.053/0.065/0.077/0.000 ms
daemon@00c22e9e7c4e:/opt/docker$

8. Docker-ui — отличный способ просмотреть и изучить ваши контейнеры.

Управление Docker с помощью Docker CLI не так сложно и обеспечивает отличную внутреннюю информацию о том, что происходит. Зачастую вам не нужна полная мощность интерфейса командной строки Docker, а просто нужен быстрый обзор того, какие контейнеры запущены, и посмотрите, что происходит. Для этого замечательным проектом является Docker ui ( https://github.com/crosbymichael/dockerui ):

контейнер

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

9. Контейнер не запускается? перезаписать точку входа и просто запустить ее из bash

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

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

1
2
3
4
5
$ docker run -ti --entrypoint=bash cassandra
root@896757f0bfd4:/# ls
bin   dev           etc   lib    media  opt   root  sbin  sys  usr
boot  docker-entrypoint.sh  home  lib64  mnt    proc  run   srv   tmp  var
root@896757f0bfd4:/#

10. Прослушивание событий внутри контейнера

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

2__docker

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