Эта заметка объяснит, как можно использовать Docker для тестирования связки клиент/прокси/сервер на одной единственной машине с RedHat 7. Для этого не требуется 3 сервера, нужен только один с 2 или 3 контейнерами. На одной машине будут и клиент, и прокси, и сервер.
Когда докер стартует, он создает виртуальный интерфейс docker0 (см. схему). При этом выбирается случайным образом незанятые на хост-машине адрес и подсеть из частного диапазона.
docker0 — это виртуальный Ethernet мост, который автоматически переправляет пакеты между другими другими сетевыми интерфейсами подключенными к нему. Это позволяет контейнерам общаться друг с другом и хост-машиной.
Основы
1. Образы докера
Образы позволяют создавать контейнеры.
2. Реестры докера
Реестры содержат образы
3. Контейнеры докера
Являются аналогами папок
— контейнер содержит все нужное для запуска приложения.
— каждый контейнер создается из образа.
— контейнер можно запустить, остановить, переместить, удалить.
— у контейнера может истечь срок действия (контейнер может «заэкспариться»).
Установка докера
1. Устанавливаем RH7.
2. устанавливаем RH7 версию докера.
cd /etc/yum.repos.d vi docker.repo |
добавляем строки:
[docker-main-repo] name=Docker ${repo} Repository baseurl=https://yum.dockerproject.org/repo/main/centos/7/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg |
после этого выполняем:
yum install docker ======================================= Installing : docker-1.2.0-1.8.el7.x86_64 Verifying : docker-1.2.0-1.8.el7.x86_64 Installed: docker.x86_64 0:1.2.0-1.8.el7 |
Полезная документация: steps
3. Проверьте, что докер установился корректно, выполнив команду:
# docker info The system information should appear: Containers: 6 Running: 0 Paused: 0 Stopped: 6 Images: 2 Server Version: 1.11.1 |
4. Если докер еще не запущен, выполните:
# service docker start Redirecting to /bin/systemctl start docker.service |
5. Проверьте запуск, выполнив команду:
ps -ef | grep docker root 815 27601 0 11:31 pts/0 00:00:00 grep --color=auto docker root 19444 1 0 May13 ? 00:04:36 /usr/bin/docker daemon -H fd:// root 19450 19444 0 May13 ? 00:00:26 docker-containerd -l /var/run/docker/libcontainerd/docker-containerd.sock --runtime docker-runc |
Конфигурирование докера (загрузка образов и создание контейнеров)
1. Скачиваем готовый образ, выполнив команду:
# docker pull ubuntu |
Вывод должен быть примерно таким:
# docker pull ubuntu Using default tag: latest latest: Pulling from library/ubuntu 6d28225f8d96: Pull complete 166102ec41af: Pull complete d09bfba2bd6a: Pull complete c80dad39a6c0: Pull complete a3ed95caeb02: Pull complete Digest: sha256:5718d664299eb1db14d87db7bfa6945b28879a67b74f36da3e34f5914866b71c Status: Downloaded newer image for ubuntu:latest |
2. Проверяем, что образ появился в докере, выполнив:
# docker images |
Ожидаемый вывод:
REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest c5f1cf30c96b 2 weeks ago 120.7 MB hello-world latest 94df4f0ce8a4 3 weeks ago 967 B centos latest 778a53015523 6 weeks ago 196.7 MB |
3. Создайте контейнер из скачанного образа:
docker run --privileged -h mydomain.myhost.com -i -t -v /spare:/spare ubuntu |
4. Проверьте, что контейнер появился (запомните его ID).
# docker ps -l |
# пока был создан только один контейнер
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fc4a829dd23f ubuntu "/bin/bash" 32 seconds ago Up 29 seconds trenched_katie |
5. Создайте из того же образа еще один контейнер:
docker run --privileged -h mydomain.myhost.com -i -t -v /spare:/spare ubuntu |
6. Проверьте, что он существует (запомните его ID):
# второй пошел! CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8e6c818e87f1 ubuntu "/bin/bash" 12 seconds ago Up 10 seconds opposed_trent |
Настройка маршрута между контейнерами
1. Создайте 2 моста на хосте:
# brctl addbr br1 # brctl addbr br2 |
2. Проверьте, что мосты появились, выполнив команду:
# ip addr 6: docker0: <broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:8c:73:8f:68 brd ff:ff:ff:ff:ff:ff inet 172.15.0.1/16 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:8cff:fe73:8f68/64 scope link valid_lft forever preferred_lft forever 18: veth6d72f5f@if17: </broadcast><broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP link/ether ea:0d:26:52:69:32 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::e80d:26ff:fe52:6932/64 scope link valid_lft forever preferred_lft forever 19: br1: </broadcast><broadcast ,MULTICAST> mtu 1500 qdisc noop state DOWN link/ether a6:51:c0:76:0b:87 brd ff:ff:ff:ff:ff:ff 20: br2: </broadcast><broadcast ,MULTICAST> mtu 1500 qdisc noop state DOWN link/ether 6e:95:43:2f:09:0c brd ff:ff:ff:ff:ff:ff </broadcast> |
3. На хост-машине надо назначить IP адреса для br1 и br2 с помощью команд:
ifconfig br1 ${lBr1IPAddress} netmask ${lSubnetMask} ifconfig br2 ${lBr2IPAddress} netmask ${lSubnetMask} |
Можно выбрать такие значения:
ifconfig br1 172.15.2.1/24 netmask 255.255.255.0 ifconfig br2 172.15.3.1/24 netmask 255.255.255.0 |
4. Проверьте, что мостам действительно назначены IP:
#ip addr 6: docker0: <broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:8c:73:8f:68 brd ff:ff:ff:ff:ff:ff inet 172.15.0.1/16 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:8cff:fe73:8f68/64 scope link valid_lft forever preferred_lft forever 18: veth6d72f5f@if17: </broadcast><broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP link/ether ea:0d:26:52:69:32 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::e80d:26ff:fe52:6932/64 scope link valid_lft forever preferred_lft forever 19: br1: </broadcast><broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN link/ether a6:51:c0:76:0b:87 brd ff:ff:ff:ff:ff:ff inet 172.15.2.1/24 brd 172.15.2.255 scope global br1 valid_lft forever preferred_lft forever inet6 fe80::1851:c0ff:fe66:b43/64 scope link valid_lft forever preferred_lft forever 20: br2: </broadcast><broadcast ,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN link/ether 6e:95:43:2f:09:0c brd ff:ff:ff:ff:ff:ff inet 172.15.3.1/24 brd 172.15.3.255 scope global br2 valid_lft forever preferred_lft forever inet6 fe80::8c95:4bff:fe2f:97c/64 scope link valid_lft forever preferred_lft forever </broadcast> |
5. Можно воспользоваться командой:
ip route 172.15.0.0/16 dev docker0 proto kernel scope link src 172.15.0.1 172.15.2.0/24 dev br1 proto kernel scope link src 172.15.2.1 172.15.3.0/24 dev br2 proto kernel scope link src 172.15.3.1 |
Пересылка запросов между контейнерами
Предполагается, что на хосте установлен httpd и добавлена в папку www какая-нибудь тестовая страничка.
1. Получаем список всех контейнеров:
#docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1eb65a781a34 centos "/bin/bash" About an hour ago Up About an hour prickly_stallman a3b38dde603a centos "/bin/bash" About an hour ago Exited (0) About an hour ago small_lovelace 55d28eae64aa hello-world "/hello" About an hour ago Exited (0) About an hour ago sick_ardinghelli 97fc942e39f6 hello-world "/hello" About an hour ago Exited (0) About a minute ago determined_curie 0d7e9943fb4d hello-world "/hello" About an hour ago Exited (0) About an hour ago clever_goldstine 37d386b7e41f hello-world "/hello" 2 hours ago Exited (0) 2 hours ago jolly_bohr |
2. Перед использованием контейнер надо запустить. Для запуска контейнера нужен ID. Мы запустим серверный и клиентский контейнеры.
# docker start 1eb65a781a34 # docker start a3b38dde603a |
Для нашей конфигурации:
client = 172.15.3.1 Server = 172.15.2.1 |
Прикрепляем контейнер:
docker attach 1eb65a781a34 |
3. Для проверки маршрута между контейнерами выполним curl запрос:
(прокси настроен на хост машине в режиме full transparency, поэтому в моем случае его нигде не надо указывать)
curl http://172.15.2.1/test.html |
< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/> </head> <body> </body><body BGcolor="#EAF1FD"> <blockquote> <h1 align="center"> <font face="Arial, Helvetica, sans-serif">Response!</font></h1> </blockquote> </body> </html> |