Docker¶
Описание¶
Docker - способ изоляции приложений на уровне linux ядра (cgoups, namespaces), то есть контейнеризация приложений.
Основные принципы:
- состоит из слоев - слепков состояний файловой системы (OverlayFS)
- докер - не виртуальная машина
- докер - контейнер с минимальным набором софта, необходимым для работы приложения
- docker-way - не хранить никаких данных внутри контейнера
- контейнер живет пока жив процесс pid=1, вокруг которого рождается контейнер
- контейнер может работать как foreground, так и в background
Docker registry - хранилища образов (напр. Docker hub).
Docker image - набор слоёв, каждый из которых результат выполнения Dockerfile. Иначе - шаблон для запуска контейнера.
- Образы хранятся в
/var/lib/docker. - Из одного образа можно запустить сколько угодно контейнеров, из которых в свою очередь можно создать другие образы (
build), то есть образы могу переиспользоваться. - Имя образа состоит из
. imageidу образа всегда один, но имена и теги могут быть разные.- Образ не будет удален, пока все теги не будут удалены.
Начало работы¶
Для работы необходимо установить docker-ce. Установка описана здесь https://docs.docker.com/engine/install/
Демо контейнер
git clone https://github.com/docker/doodle.git
# BUILD container
# -t -
cd doodle\cheers2019 ; docker build -t 3xh4l3/cheers2019 .
# RUN container
# -i - interactive. Keep stdin open.
# -t - alloc pseudo tty
# -rm - remove container after exit
docker run -it --rm 3xh4l3/cheers2019
docker login &&
docker push 3xh4l3/cheers2019
daemon.json¶
- Включаем поддержку IPv6
- Меняем стандартную адресацию докера на свою
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64",
"bip": "100.80.0.1/12",
"default-address-pools": [{
"base": "100.80.0.0/12",
"size": 24
}]
}
Команды¶
Общее¶
# Запустить свой registry
docker run -d -p 5000:5000 --restart=always --name registry registry:2
# Удалить вообще все. Фактически сбросить к исходному состоянию
docker system prune -a
# Список сетей
docker network ls
# Настройки конкретной сети
docker network inspect <network name>
Образы¶
Создать образ можно командой docker build <context>
В качестве context может быть локальная директория или ссылка на git репозиторий или tar файл. Также можно передать через pipe один Dockerfile.
Примеры
# Список загруженных или собственных сбилженных образов
docker images
# Создание
docker build .
docker build -t <imagename> <directory with Dockerfile>
docker build --no-cache -t ...
docker build - < Dockerfile
docker build - < context.tar.gz
docker build github.com/creack/docker-firefox
# Переименовать образ
docker tag <existing image name> <new image name>
# Загрузить образ в reigstry (например dockerhub)
docker push <repository>
# Скачать образ
docker pull wallarm/node
# Удалить образ
docker rmi <image>
Ключи:
- --no-cache - полностью пересоздать образ
- -t - название будущего образа (name:tag)
- -f - Dockerfile (по-умолчанию PATH/Dockerfile)
Контейнеры¶
# Список запущенных контейнеров
docker ps
# Создать контейнер
docker run -name=<container> <image> <process>
# Запустить ранее остановленный контейнер
docker start <container>
# Остановка контейнера
docker container stop <container> # SGITERM
docker container kill <container> # SIGKILL
# Удалить контейнер(ы)
docker rm <container id>
docker container rm -f $(docker ps -aq) # Удалить все
docker container rm $(docker ps –aq) # Удалить только остановленные
# Выполнить команду в запущенном контейнере
docker exec -it <container> <command>
# Запустить контейнер, чтобы протестировать какую-нибудь фичу
docker run --name=php-test --rm -ti php:7.1-fpm-alpine /bin/sh
Хитрости¶
Посмотреть, какой командой был запущен контейнер
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike <container>
Dockerfile¶
Best ptractices https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
Для создания своих образов используется docker build, который берет набор инструкций из Dockerfile.
Dockerfile - набор инструкций для создания нового образа.
- Каждая законченная команда создает новый слой - результат выполнения команды.
- Слои независимы друг от друга. Связанные команды должны запускаться черезе
&&. - Постоянные данные сохраняются от слоя к слою.
Директивы:
-
FROM - образ, на основе которого создается контейнер или новый образ
-
MAINTAINER - автор
-
RUN - выполняет команды, результатом которых является новый слой (образ), который в свою очередь используется для следующих инструкций. То есть эта директива подготавливает контейнер к запуску процесса (
CMD). Юзаем&&и переносы\для длинных команд.
# Команды можно запускать через &&
RUN echo 1 \
&& echo 2 \
&& echo 3
# Можн установить аргументы
# -e - немедленно выйти, если какая-либо команда завершилась с ошибкой
# -x - вывод каждой выполняемой команды (полезно при дебаге)
RUN set -ex \
&& ...
- CMD - определяет, какая команда (процесс) будет запущена в контейнере
Может быть только одна инструкция
CMDв докерфайле Процесс не должен уходить в background Вывод можно оставлять в stdout - ENTRYPOINT - если в
CMDпередаются только аргументы без исполняемого файла, то исполняемый файл должен быть указан в данной директиве, то есть итоговая команда =ENTRYPOINT+CMD - COPY - скопировать в контейнер файлы из текущей директории
- EXPOSE - указать, какие порты показать наружу внутри сети докера. Чтобы этот порт был доступен с хост системы, нужно сделать маппинг портов в хост систему.
docker run -p 80:80 <image>Внутри контейнера нельзя биндиться на локалхост
- ADD -
Порядок директив в докерфайле очень важен, поскольку ребилд происходит с той команды, которая была изменена.
Примеры¶
rabbitmq
FROM rabbitmq:management
ADD rabbitmq.conf /etc/rabbitmq/rabbitmq.conf
ADD definitions.json /etc/rabbitmq/
RUN chown rabbitmq:rabbitmq /etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/definitions.json
CMD ["rabbitmq-server"]
Docker-compose¶
Docker-compose - yaml файл, который описывает как запускать и связывать между собой контейнеры для служб работающих обычно в связке. Например MySQL+Apache.
# Поднять один из контейнеров стека
docker-compose up -d postgres
Systemd¶
Для удобного запуска контейнеров их легко можно засунуть в systemd. Для этого создаем сервисфайл:
>/etc/systemd/system/example.service
systemctl daemon-reload
systemctl edit --full example.service
Содержимое файла
[Unit]
Description=My example service in docker
Requires=docker.service
After=docker.service
[Service]
Restart=always
RestartSec=3
ExecStartPre=/bin/sh -c "/usr/bin/docker rm -f example 2> /dev/null || /bin/true"
ExecStart=/usr/bin/docker run --rm -a STDIN -a STDOUT -a STDERR -p 80:80 --name example
ExecStop=/usr/bin/docker stop example
[Install]
WantedBy=multi-user.target
systemctl restart example.service
journalctl -u example.service --no-pager -f
Полезные сборки¶
php7-fpm + gd¶
latest
FROM php:7.0-fpm-alpine
RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev && \
docker-php-ext-configure gd \
--with-freetype \
--with-jpeg && \
docker-php-ext-install -j$(nproc) gd && \
apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev
WORKDIR /usr/share/nginx/html/
#ADD /root/php.ini /usr/local/etc/php/conf.d/40-custom.ini
CMD ["php-fpm"]
7.0
FROM php:7.0-fpm-alpine
RUN apk add --no-cache freetype libpng libjpeg-turbo freetype-dev libpng-dev libjpeg-turbo-dev libxml2-dev libwebp-dev libxpm-dev
RUN docker-php-ext-install xml
RUN docker-php-ext-configure gd \
--with-gd \
--with-webp-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib-dir \
--with-xpm-dir \
--with-freetype-dir \
--enable-gd-native-ttf && \
docker-php-ext-install -j$(nproc) gd && \
apk del --no-cache freetype-dev libpng-dev libjpeg-turbo-dev
WORKDIR /usr/share/nginx/html/
ADD php.ini /usr/local/etc/php/conf.d/40-custom.ini
CMD ["php-fpm"]
php.ini
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT
display_errors = on
short_open_tag = on
post_max_size = 200M
upload_max_filesize = 200M
date.timezone = Asia/Krasnoyarsk
;заремарить следующую строку, иначе письма будут терять поле FROM
mail.add_x_header = of
python¶
Классическое приложение
# first stage
FROM python:3.8 AS builder
COPY requirements.txt .
# install dependencies to the local user directory (eg. /root/.local)
RUN pip install --user -r requirements.txt
# second unnamed stage
FROM python:3.8-slim
WORKDIR /code
# copy only the dependencies installation from the 1st stage image
COPY --from=builder /root/.local /root/.local
COPY ./src .
# update PATH environment variable
ENV PATH=/root/.local:$PATH
CMD [ "python", "./server.py" ]
Тестовые окружения¶
Всяческие локальные среды для быстрого тестирования.
MySQL¶
docker volume create mysql-volume
docker run --name=test-mysql -p3306:3306 -v mysql-volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql/mysql-server:5.7
# Проверяем, что запустился
docker logs mk-mysql
# Логинимся, чтобы разрешить root подключаться не только с локалхоста
docker exec -it test-mysql bash
# Консоль контейнера
mysql -u root -p
# MySQL консоль
mysql> update mysql.user set host = ‘%’ where user=’root’;
mysql> flush privileges;