Docker
Материал из Xgu.ru
Docker — opensource-приложение/проект/инфраструктура, позволяющая упаковывать, распространять, устанавливать и использовать opensource-приложения.
Приложения работают в изолированной среде (построенной с помощью пространств имён, namespaces, и групп процессов, cgroups), с одной стороны изолируя процессы друг от друга, с другой стороны не прибегая при этом к таким избыточным средствам как виртуализация или эмуляция.
Система написана на Go. Работает в различных UNIX/Linux-системах, ожидается, что в недалёком будущем будет поддерживаться и Windows.
Docker чаще всего использует различные системы виртуализации на уровне ОС, в настоящее время наибольшее распространение получила комбинация Docker + LXC, на которой он и был первоначально основан. Это привело к тому, что многие путают Docker и LXC, в действительности, естественно, это совершенно разные проекты с разными функциями.
В чём принципиальное отличие Docker от LXC:
http://stackoverflow.com/questions/17989306/what-does-docker-add-to-just-plain-lxc
Содержание |
[править] Первые шаги
[править] Установить Docker
echo deb http://get.docker.io/ubuntu docker main | sudo tee /etc/apt/sources.list.d/docker.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 sudo apt-get update sudo apt-get install -y lxc-docker
[править] Найти и установить контейнер
docker search tutorial docker pull learn/tutorial
[править] Выполнить команды внутри контейнера
docker run apt-get update
Эти же команды можно выполнить с помощью скрипта: curl -sSL https://get.docker.com/ubuntu/ |
[править] Базовые операции с контейнерами
[править] Список контейнеров
docker ps
[править] Просмотреть вывод контейнера
docker logs
В режиме tail -f:
docker logs -f
[править] Просмотреть конфигурацию контейнера
Просмотреть конфигурацию контейнера в JSON-формате:
docker inspect container_name
Просмотреть отдельную часть конфигурации/переменную:
docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name
[править] Основные команды по работе с контейнерами (Docker cheatsheet)
[править] Жизненный цикл
- docker create
- создать контейнер, но не запускать его
- docker run
- создать и запустить контейнер
- docker stop
- остановить контейнер
- docker start
- запустить существующий остановленный контейнер
- docker restart
- перезапустить контейнер
- docker rm
- удалить контейнер
- docker kill
- отправить сигнал SIGKILL контейнеру
- docker attach
- подключиться к работающему контейнеру
- docker wait
- блокировать команду и ждать, пока контейнер не остановится
[править] Информация о контейнерах
- docker ps
- показать работающие контейнеры (или вообще контейнеры, если использовать дополнительные опции)
- docker inspect
- показать всю информацию о контейнере, включая IP-адреса
- docker logs
- показать лог-вывод контейнера
- docker events
- показать события контейнера
- docker port
- показать открытые наружу порты контейнера
- docker top
- показать процессы, работающие внутри контейнера
- docker stats
- показать статистику использования ресурсов контейнером
- docker diff
- показать изменённые файлы в файловой системе контейнера
[править] Импорт/экспорт
docker cp copies files or folders out of a container's filesystem. docker export turns container filesystem into tarball archive stream to STDOUT.
[править] Выполнение команд
docker exec to execute a command in container.
[править] Создание контейнера / докеризация приложения
Рассмотрим, как можно создать docker-контейнер, в котором будет работать flask-приложение. Потом сделаем приложение доступным через nginx-сервер, работающий в отдельном контейнере.
[править] Создание Docker-файла
FROM python:2.7 RUN mkdir -p /code COPY . /code VOLUME [ "/code" ] WORKDIR /code RUN pip install -r requirements.txt EXPOSE 5000 CMD [ "python", "/code/app.py" ]
В текущем каталоге должны быть размещены:
app.py
from flask import Flask from redis import Redis import os app = Flask(__name__) redis = Redis(host='redis', port=6379) @app.route('/') def hello(): redis.incr('hits') return 'Hello World! I have been seen %s times.' % redis.get('hits') if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
requirements.txt
flask redis
[править] Сборка образа
docker build -t flaskapp .
[править] Запуск контейнера с новым образом
docker run -d -P --name flaskapp flaskapp
Просмотреть, работает ли контейнер, и на каком порту он доступен:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0c8339084e07 flaskapp:latest "python /code/app.py 5 seconds ago Up 3 seconds 0.0.0.0:49154->5000/tcp flaskapp
Если обратиться на порт 49154 хост-системы, будет получен доступ к приложению, работающему внутри контейнера.
Поскольку наше приложение использует для своей работы внешний сервис (redis), нам потребуется контейнер с redis, который будет подключен к этому контейнеру.
docker rm -f flaskapp docker run -d --name redis redis docker run -d -P --name flaskapp --link redis:redis flaskapp
Теперь нашему приложению доступен Redis-сервер.
[править] Подключить дополнительные образы
При необходимости можно подключить дополнительные образы Docker, создать связку контейнеров.
Создадим nginx-контейнер, который является сетевым фронтендом для flask-приложения.
Создадим конфигурационный файл nginx назовём flaskapp.conf:
server { listen 80; location / { proxy_pass http://flaskapp:5000; } }
Создадим Dockerfile:
FROM nginx:1.7.8 COPY flaskapp.conf /etc/nginx/conf.d/default.conf
После этого нужно построить и запустить образ:
docker build -t nginx-flask . docker run --name nginx-flask --link flaskapp:flaskapp -d -p 8080:80 nginx-flask
Сейчас работает три контейнера, которые взаимосвязаны друг с другом:
+-------+ +-------+ +-------+ 8080| | 5000| | | | o nginx +----->o flask +----->| redis | | | | | | | +-------+ +-------+ +-------+
Работающие контейнеры:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 980b4cb3002a nginx-flask:latest "nginx -g 'daemon of 59 minutes ago Up 59 minutes 443/tcp, 0.0.0.0:8080->80/tcp nginx-flask ae4320dc419a flaskapp:latest "python /code/app.py About an hour ago Up About an hour 0.0.0.0:49161->5000/tcp flaskapp 3ecaab497403 redis:latest "/entrypoint.sh redi About an hour ago Up About an hour 6379/tcp redis
Проверим, отвечает ли наш сервис:
$ curl http://5.9.243.189:8080/ ; echo Hello World! I have been seen 1 times. $ curl http://5.9.243.189:8080/ ; echo Hello World! I have been seen 2 times. $ curl http://5.9.243.189:8080/ ; echo Hello World! I have been seen 3 times.
[править] Дисковая подсистема Docker
Различные бэкенды Docker, существующие на сегодняшний день:
- vfs;
- devicemapper;
- btrfs;
- aufs.
- Comprehensive Overview of Storage Scalability in Docker (англ.)
- Thin Provisioning with Device Mapper (англ.)
[править] Доступ внутрь контейнера
В новых версиях Docker (начиная с 1.3) вы можете подключиться внутрь контейнера с помощью docker exec:
docker run --name ubuntu_bash --rm -i -t ubuntu bash docker exec -d ubuntu_bash touch /tmp/execWorks
В результате будет создан файл /tmp/execWorks.
В более старых версиях нужно использовать команду nsenter напрямую. Эта команда, кстати, может быть полезна не только с docker, но и в других случаях доступа внутрь namespace'ов.
Само собой, что кроме этих способов всегда есть возможность запустить sshd внутри контейнера и подключиться к нему с помощью ssh. Однако, это не очень правильный метод (смотрите ниже статью на эту тему).
- docker exec (англ.)
- man nsenter (англ.)
- https://blog.docker.com/tag/nsenter/
- https://github.com/jpetazzo/nsenter
- http://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil/
[править] Зачем может быть нужен Docker?
Почему Docker это хорошо?
- Контейнеры Docker кроссплатформены. Один и тот же контейнер может использоваться под разными операционными системами.
- Docker отделяет приложения от инфраструктуры. Описание инфраструктуры в терминах образов Docker помогает держать инфраструктуры в обозримом легко контролируемом состоянии;
- Выполнение приложений в контейнерах изолирует их от внешнего мира, открывая только те ресурсы, которые явно указаны. Это сводит к минимум неучтённое внешнее влияние;
- Автоматическая подготовка окружения и установка приложения. Docker делает это автоматически.
Зачем может быть нужен Docker?
- Создание сложной гетерогенной системы, включающей большое множество взаимосвязанных подсистем/служб, и сохранение её в обозримом управляемом состоянии;
- Создание собственной PaaS-инфраструктуры;
- Предоставление какого-то программного обеспечения в SaaS-модели (например, memcached-as-a-Service);
- Создание изолированных инстанций для тестирования программного обеспечения/конфигураций;
- Быстрое создание и удаление своих игровых песочниц в ходе изучения нового программного обеспечения (не нужно готовить отдельную виртуальную машину и портить свою рабочую машину, экспериментировать можно в Docker-контейнере).
[править] Вопросы и ответы
[править] Тома снаружи защищённые SELinux не доступны внутри контейнеров?
Да.
Разрешить доступ можно следующим образом:
chcon -Rt svirt_sandbox_file_t /path/to/volume
Подробнее:
[править] Дополнительная информация
- Docker User Guide (англ.)
- Docker: How to use your own Registry (англ.) — как создать свой собственный registry-сервер
Построение кластера контейнеров:
- kubernetes (англ.) — Container Cluster Manager from Google
- kubernetes , код Kubernetes на GitHub