no-style

Конфигурация Docker


Как работает Dockerfile

Если по простому то Dockerfile это такой специальный служебный фаил Docker, который описывает все внутренности docker image. Он содержит в себе участки такие как инструкции, а также слои из которых состоит образ для докер контейнера.







Как работают слои в Dockerfile

Слои представляют из себя некие заранее заготовленные слепки разных систем. Например свежеустановленная убунта - может быть взята в качестве слоя. И вы можете построить свой образ = image на основе этого слоя.







Как работают инструкции в Dockerfile

К инструкциям относятся разнообразные команды для взаимодействия и автоматизации. Например инструкция WORKDIR назначит рабочую папку которая будет использована в качестве папки по умолчанию вашего приложения внутри докер образа или контейнера.

Инструкция COPY - в процессе создания образа копирует необходимые фаилы в необходимую дирректорию. При указании Инструкции WORKDIR можно копировать фаилы из текущей директорию в рабочую папку приложения при помощи инструкции COPY . .

Инструкция RUN - запускает необходимые действия во время создания образа. Это может быть например установкой необходимых пакетов или обновлением их же. Пример

RUN apt-get update && apt get upgrade

Инструкция CMD - в отличии от инструкции RUN которая используется для создания образа, CMD - запускается каждый раз когда мы запускаем образ. По сути эта инструкция запускает само наше приложение. CMD представляет собой некий массив который содержит в себе несколько элементов. Каждый элемент предствален в виде одной команды. Например

CMD ["node", "app.js"]

Инструкция EXPOSE - определяет какой порт будет выставлен наружу. Тот порт на котором работает наше приложение. Не является обязательной.

EXPOSE 1337






Пример создания простого Dockerfile

Предположим у нас есть небольшое демонстрационное Python приложение. Всего один фаил index.py с таким содержанием:

print('Hello Python')

Чтобы завернуть наше приложение в docker image, мы создаём специальный фаил Dockerfile

Данный фаил не должен иметь никакого расширения. Он описывает структуру нашего контейнера - из чего она состоит.

Наполним Dockerfile необходимым для примера содержимым

FROM python

WORKDIR /app

COPY . .

CMD ["python", "index.py"]

В данном случае COPY . . означает скопировать всё из текущей папки в папку WORKDIR то есть в /app







Как работает Docker build

Для того чтобы сбилдить наше приложение в формат docker image необходимо написать

docker build .

Чтобы задать имя и тэг нашему image используем команду

docker build -t myimage .

Тэг или же версия вписывается вот так через двоеточие

docker build -t myimage:13.3 .






Как работает запуск и остановка контейнеров

virtualization-docker-configuration-docker-build-1

Для того чтобы запустить наш image в docker контейнере мы берём его id'шник из выхлопа docker image ls и запускаем такой командой

docker run [id или name]

Остановка происходит при помощи интуитивно-понятной команды

docker stop [id или name]

после остановки контейнера мы можем снова запустить его командой

docker start [id или name]

Отличия между командами docker run и docker start заключается в том что при использовании команды docker run мы взаимодействуем непосредственно с образом. А docker start в свою очередь работает уже с контейнером.

Так же бывает полезно попасть в шелл уже запущенного контейнера, для этого выполняется команда

docker attach [id или name]

Если мы запускали контейнер через docker-compose то тогда команда будет такая

docker exec -it [container id] bash






Режимы запуска docker run

Интерактивный режим.

В данном режиме мы попадаем в интерактивную консоль внутри контейнера. Для примера будем использовать интерактивный режим с образом node js.

Выполнив команду ниже мы попадём в консоль node js и можем работать с ней точно так же как как если бы она была установлена у нас локально, а не в контейнере.

docker run -it node

Deatached режим

Данный режим используется если мы просто хотим запустить контейнер. Без интерактивного шелла. То есть при запуске мы не будем попадать внутрь контейнера в терминале, а только запустим этот контейнер.

docker run -d node






Параметры запуска docker run

Параметр -p обладает своим специальным синтаксисом, в котором мы указываем два набора портов. Вначале идёт порт который мы открываем наружу на хостовой машине. Потом идёт разделитель в виде двоеточия : и после разделителя пишется порт внутри контейнера. Таким образом можно замапить наружу любой порт из контейнера.

docker run -p 80:8080 [id или name]

Параметр --name используется для того чтобы задать имя контейнеру

docker run --name testcontainer [id или name]

Параметр --rm будет полезен в случае когда мы хотим удалить наш контейнер сразу после его остановки

docker run --rm [id или name]






Отличия Docker image от Docker container

Следует понимать что в отличии от докер контейнера, docker image = read only. Проще говоря docker image является как бы болванкой которую мы берём в качестве базы под докер контейнер.

Большая часть docker имаджей(image) находится на официальном сайте docker hub, который очень напоминает гитхаб. Тут находится огромная библиотека официальных образов таких как nginx, mysql и другие, так и просто образы от любителей энтузиастов.







Управление образами Docker image

Мы можем скачать образ. Например скачаем образ nodejs

docker pull node

Отобразить все имеющиеся docker image

docker image ls

Удалить образ

docker rmi node

Удалить все неиспользуемые образы

docker image prune

Посмотреть детализированную информацию конкретных docker image

docker image inspect [id или name]






Управление контейнерами

Отобразить список активных контейнеров

docker ps

Отобразить список всех контейнеров, включая неактивные

docker ps -a

Удаление контейнера

docker rm [id или name]

Мы можем удалить все приостановленные и неиспользуемые в данный момент контейнеры командой

docker container prune






Фаил .dockerignore

Работает по такому же принципу как и похожий фаил в git.

Мы создаём в корне нашего проекта фаил .dockerignore и заносим в него все те вещи которые нам не потребуется переносить в docker image.

Пример:

node_modules
secret
.git
Dockerfile






Взаимодействие с переменными окружения и .env фаилами

Предположим что мы открываем наружу порт в Dockerfile таким образом

ENV PORT 1337
EXPOSE $PORT

И после этого билдим и запускаем контейнер

docker build -t testapp:env .
docker run -d -p 80:1337 --rm --name envtest testapp:env

У нас всё прекрасно запускается. Теперь попробуем другой способ. В котором мы дополнительно укажем enviroment команду -e

Её синтаксис такой ... -e ключ=значение

если нам необходимо указать несколько переменных окружения то мы можем вписать их друг за другом -e PORT=80 -e IP=1.1.1.1

Пробуем запустить с переменной окружения. Обратите внимание как поменялся порт, который в Dockerfile у нас указан 1337

docker run -d -p 80:8888 -e PORT=8888 --rm --name envtest testapp:env

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

Для примера создадим папку config и внутри неё фаил .env с таким содержанием

PORT=1337

И стартанём ещё один контейнер но уже с учётом только что созданного .env фаила

docker run -d -p 80:1337 --env-file ./config/.env --rm --name envtest testapp:env






Упрощаем работу с контейнером при помощи make фаила

Мы можем вынести необходимые параметры запуска в отдельный фаил - Makefile. При с помощью этого фаила мы будем запускать наш контейнер

Создаём в корне проекта фаил с именем Makefile

Внутри этого фаила мы описываем одну или несколько команд, которые будут служить нам в качестве шорткатов

run:
    docker run -d -p 80:1337 --env-file ./config/.env --rm --name envtest testapp:env
stop:
    docler stop envtest

Теперь для того чтобы запустить контейнер достаточно написать

make run

а остановить соответственно

make stop






Docker Volumes

Docker volume это некая сущность которая играет роль виртуального жесткого диска.

По стандарту если мы специально не обозначаем volume для контейнера, то создаётся анонимный volume. Самое важное что необходимо знать про анонимные volum'ы что они удаляются вместе с контейнером. То есть была у нас например база данных, мы наполняли её данными а затем удалили контейнер - данные удаляются вместе с ним.

Если же необходимо сохранить данные полученные в результате работы контейнера, то мы можем объявить именованный volume. Проще говоря мы указываем докеру папку в которой зеркалим папку внутри контейнера. В результате в выбранной нами локальной папке появятся данные из контейнера. Делается это так локальнаяпапка:папкавнутриконтейнера

Запуск контейнера с именованным volume на примере nginx

docker run -d -v /app/public_html:/usr/share/nginx/html:ro nginx

То есть сначала мы указываем папку на хостовой системе /app/public_html и через двоеточие папку внутри контейнера /usr/share/nginx/html:ro

Кстати :ro означает read only - имеет смысл ставить на статические фаилы. Мы всё равно можем менять их внутри нашей папки /app/public_html и они будут меняться в контейнере.

В Dockerfile volume описывается при помощи инструкции VOLUME вот так

VOLUME [ "/app/data" ]

Если мы в докерфаиле копируем наши фаилы внутрь /app то логично будет монтировать volume в эту папку

docker run -d -v /home/user/project1/app:/app myimage

При этом совсем не обязательно на хосте мапить это по абсалютному пути. Можно использовать относительный путь. Например в той папке в которой мы сейчас находимся замапить папку Data на папку /app внутри контейнера

docker run -d -v ./Data:/app myimage

Создать volume

docker volume create [название]

Удалить volume

docker volume rm [название]

Отобразить список Volume'ов

docker volume ls

Посмотреть подробную информацию о конкретном volume

docker volume inspect [название]






Как загрузить свой образ на dockerhub

В первую очередь необходимо зарегистрироваться на DockerHub.

Необходимо войти в свою учётную запись с помощью команды

docker login

Находим нужный нам имадж. Если его нет то билдим

docker images


Есть определённые требования к названию образа. Он должен называться как dockerhubusername/imagename:tagname

Чтобы правильно назначить имя перед загрузкой образа выполняем команду

docker tag имяобраза dockerhubusername/imagename:tagname

Например вот так

docker tag myimage:test username/myimage:test


Для того чтобы загрузить образ на докерхаб используем команду

docker push DockerHubUsername/ImageName:TagName

Вот так

docker push username/myimage:test

При этом Tagname который идёт после двоеточия использовать не обязательно, но он поможет нам не запутаться в версиях


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

docker pull username/myimage:test