Как работает Dockerfile
Если по простому то Dockerfile это такой специальный служебный фаил Docker, который описывает все внутренности docker image. Он содержит в себе участки такие как инструкции, а также слои из которых состоит образ для докер контейнера.
Как работают слои в Dockerfile
Слои представляют из себя некие заранее заготовленные слепки разных систем. Например свежеустановленная убунта - может быть взята в качестве слоя. И вы можете построить свой образ = image на основе этого слоя.
Как работают инструкции в Dockerfile
К инструкциям относятся разнообразные команды для взаимодействия и автоматизации. Например инструкция WORKDIR назначит рабочую папку которая будет использована в качестве папки по умолчанию вашего приложения внутри докер образа или контейнера.
Инструкция COPY - в процессе создания образа копирует необходимые фаилы в необходимую дирректорию. При указании Инструкции WORKDIR можно копировать фаилы из текущей директорию в рабочую папку приложения при помощи инструкции COPY . .
Инструкция RUN - запускает необходимые действия во время создания образа. Это может быть например установкой необходимых пакетов или обновлением их же. Пример
Инструкция CMD - в отличии от инструкции RUN которая используется для создания образа, CMD - запускается каждый раз когда мы запускаем образ. По сути эта инструкция запускает само наше приложение. CMD представляет собой некий массив который содержит в себе несколько элементов. Каждый элемент предствален в виде одной команды. Например
Инструкция EXPOSE - определяет какой порт будет выставлен наружу. Тот порт на котором работает наше приложение. Не является обязательной.
Пример создания простого Dockerfile
Предположим у нас есть небольшое демонстрационное Python приложение. Всего один фаил index.py с таким содержанием:
Чтобы завернуть наше приложение в docker image, мы создаём специальный фаил Dockerfile
Данный фаил не должен иметь никакого расширения. Он описывает структуру нашего контейнера - из чего она состоит.
Наполним Dockerfile необходимым для примера содержимым
WORKDIR /app
COPY . .
CMD ["python", "index.py"]
В данном случае COPY . . означает скопировать всё из текущей папки в папку WORKDIR то есть в /app
Как работает Docker build
Для того чтобы сбилдить наше приложение в формат docker image необходимо написать
Чтобы задать имя и тэг нашему image используем команду
Тэг или же версия вписывается вот так через двоеточие
Как работает запуск и остановка контейнеров

Для того чтобы запустить наш image в docker контейнере мы берём его id'шник из выхлопа docker image ls и запускаем такой командой
Остановка происходит при помощи интуитивно-понятной команды
после остановки контейнера мы можем снова запустить его командой
Отличия между командами docker run и docker start заключается в том что при использовании команды docker run мы взаимодействуем непосредственно с образом. А docker start в свою очередь работает уже с контейнером.
Так же бывает полезно попасть в шелл уже запущенного контейнера, для этого выполняется команда
Если мы запускали контейнер через docker-compose то тогда команда будет такая
Режимы запуска docker run
Интерактивный режим.
В данном режиме мы попадаем в интерактивную консоль внутри контейнера. Для примера будем использовать интерактивный режим с образом node js.
Выполнив команду ниже мы попадём в консоль node js и можем работать с ней точно так же как как если бы она была установлена у нас локально, а не в контейнере.
Deatached режим
Данный режим используется если мы просто хотим запустить контейнер. Без интерактивного шелла. То есть при запуске мы не будем попадать внутрь контейнера в терминале, а только запустим этот контейнер.
Параметры запуска docker run
Параметр -p обладает своим специальным синтаксисом, в котором мы указываем два набора портов. Вначале идёт порт который мы открываем наружу на хостовой машине. Потом идёт разделитель в виде двоеточия : и после разделителя пишется порт внутри контейнера. Таким образом можно замапить наружу любой порт из контейнера.
Параметр --name используется для того чтобы задать имя контейнеру
Параметр --rm будет полезен в случае когда мы хотим удалить наш контейнер сразу после его остановки
Отличия Docker image от Docker container
Следует понимать что в отличии от докер контейнера, docker image = read only. Проще говоря docker image является как бы болванкой которую мы берём в качестве базы под докер контейнер.
Большая часть docker имаджей(image) находится на официальном сайте docker hub, который очень напоминает гитхаб. Тут находится огромная библиотека официальных образов таких как nginx, mysql и другие, так и просто образы от любителей энтузиастов.
Управление образами Docker image
Мы можем скачать образ. Например скачаем образ nodejs
Отобразить все имеющиеся docker image
Удалить образ
Удалить все неиспользуемые образы
Посмотреть детализированную информацию конкретных docker image
Управление контейнерами
Отобразить список активных контейнеров
Отобразить список всех контейнеров, включая неактивные
Удаление контейнера
Мы можем удалить все приостановленные и неиспользуемые в данный момент контейнеры командой
Фаил .dockerignore
Работает по такому же принципу как и похожий фаил в git.
Мы создаём в корне нашего проекта фаил .dockerignore и заносим в него все те вещи которые нам не потребуется переносить в docker image.
Пример:
secret
.git
Dockerfile
Взаимодействие с переменными окружения и .env фаилами
Предположим что мы открываем наружу порт в Dockerfile таким образом
EXPOSE $PORT
И после этого билдим и запускаем контейнер
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
Теперь рассмотрим ещё один более удобный способ. Если вы работаете с большим количеством env переменных то проще создать фаил в котором мы будем хранить все наши переменные окружения. Обычно его называют .env но это может быть любое удобное вам название - которое не пересекается с другими служебными названиями.
Для примера создадим папку config и внутри неё фаил .env с таким содержанием
И стартанём ещё один контейнер но уже с учётом только что созданного .env фаила
Упрощаем работу с контейнером при помощи make фаила
Мы можем вынести необходимые параметры запуска в отдельный фаил - Makefile. При с помощью этого фаила мы будем запускать наш контейнер
Создаём в корне проекта фаил с именем Makefile
Внутри этого фаила мы описываем одну или несколько команд, которые будут служить нам в качестве шорткатов
docker run -d -p 80:1337 --env-file ./config/.env --rm --name envtest testapp:env
stop:
docler stop envtest
Теперь для того чтобы запустить контейнер достаточно написать
а остановить соответственно
Docker Volumes
Docker volume это некая сущность которая играет роль виртуального жесткого диска.
По стандарту если мы специально не обозначаем volume для контейнера, то создаётся анонимный volume. Самое важное что необходимо знать про анонимные volum'ы что они удаляются вместе с контейнером. То есть была у нас например база данных, мы наполняли её данными а затем удалили контейнер - данные удаляются вместе с ним.
Если же необходимо сохранить данные полученные в результате работы контейнера, то мы можем объявить именованный volume. Проще говоря мы указываем докеру папку в которой зеркалим папку внутри контейнера. В результате в выбранной нами локальной папке появятся данные из контейнера. Делается это так локальнаяпапка:папкавнутриконтейнера
Запуск контейнера с именованным volume на примере nginx
То есть сначала мы указываем папку на хостовой системе /app/public_html и через двоеточие папку внутри контейнера /usr/share/nginx/html:ro
Кстати :ro означает read only - имеет смысл ставить на статические фаилы. Мы всё равно можем менять их внутри нашей папки /app/public_html и они будут меняться в контейнере.
В Dockerfile volume описывается при помощи инструкции VOLUME вот так
Если мы в докерфаиле копируем наши фаилы внутрь /app то логично будет монтировать volume в эту папку
При этом совсем не обязательно на хосте мапить это по абсалютному пути. Можно использовать относительный путь. Например в той папке в которой мы сейчас находимся замапить папку Data на папку /app внутри контейнера
Создать volume
Удалить volume
Отобразить список Volume'ов
Посмотреть подробную информацию о конкретном volume
Как загрузить свой образ на dockerhub
В первую очередь необходимо зарегистрироваться на DockerHub.
Необходимо войти в свою учётную запись с помощью команды
Находим нужный нам имадж. Если его нет то билдим
Есть определённые требования к названию образа. Он должен называться как dockerhubusername/imagename:tagname
Чтобы правильно назначить имя перед загрузкой образа выполняем команду
Например вот так
Для того чтобы загрузить образ на докерхаб используем команду
Вот так
При этом Tagname который идёт после двоеточия использовать не обязательно, но он поможет нам не запутаться в версиях
Для того чтобы на другом сервере скачать имадж с нашего репозитория