Docker-compose
Создание инфраструктуры для работы приложения.
Клонируем проект:
Нам понадобится приложение,которое мы собираемся развернуть на проекте.
git clone https://github.com/gasick/docker-compose-exempleapp --branch onlyapp
Если вы не знаете с чего начать, тогда смотрите в README проекта. Обычно в нем разрабочики указывают подготовительные шаги для того, чтобы развернуть приложени локально. Это позволит набросать какой-то простой пример Dockerfile от которого уже можно будет двигаться дальше. Ошибки при создании докер файла будет говорить, о том, что нам необхдимо добавить в докер, чтобы приложение могло запуститься.
Наша задача автоматизировать шаги развертывания приложения.
Результатом нашей работы должна получиться подобнаяструктура папок:
.
├── docker-compose.yml
├── Dockerfile
├── example.env
└── todoapp
├── go.mod
├── go.sum
└── todo.go
-
todoapp
- папка в которой хранится проект который необходимо развернуть -
Dockerfile
- файл создания контейнера с приложением внутри -
docker-compose.yml
- файл конфигурацией инфраструктуры нашего приложения, то есть наше приложение обернутое в контейнера, а так же все сервисы необходимые для его работы. -
example.env
- пример настроек для простоты перемещения проекта.
Упаковываем приложение в docker контейнер
В нашем примере, мы воспользуемся двумя контейнерами. Один будет использоваться для построения приложения, другой уже для его запуска.
Dockerfile
# Указываем какой образ мы будем использовать в качестве основы проекта, и присвоем ему имя build
FROM golang:1.16 as build
# Устанавливаем необходимое по, в данном случае это только git но этот список может быть сильно больше.
RUN apt update && apt install -y git
# Указываем рабочую папку
WORKDIR /app
# Копируем в рабочую папку необходимые файлы
COPY todoapp/go.mod .
COPY todoapp/go.sum .
# Подготавливаем окружение, скачиваем необхдимые для построения зависимости.
RUN go mod download
# Копируем проект
COPY todoapp .
# Запускаем build проекта
RUN go build -o /out/app /app
# Теперь на основе нового образа будем создавать сам рабочий контейнер.
FROM fedora
# Копируем из базового образа наше приложение для указания образа используется ключ --from=build
COPY --from=build /out/app /app
# Указываем директиву с которой будет запускаться проект
CMD ["/app"]
# Так как проект слушает порт для подключения клиентов, выставляем его.
EXPOSE 8000
Тепреь давайте прверим, что Dockerfile коректен и мы можем упаковать наше приложение:
docker build -t test .
Если билд прошел, и все шаги отработали идем дальше. Запускать проект пока не нужно, он всё равно выдаст ошибку, так как для работы необходим Postgres.
Создаем docker-compose, связываем приложение и базу данных в одну инфраструктуру.
docker-compose.yml
version: "3"
services:
todoapp:
build: .
ports:
- 8000:8000
env_file:
- example.env
depends_on:
- postgres
postgres:
image: postgres:13-alpine
restart: always
env_file:
- example.env
volumes:
- ./postgres/data:/var/lib/postgresql/data
- ./postgres/dumps:/dumps
example.env
Для полноценной работы в проекте нам нужен example.env.
Вынесение переменных окружения позволяет легко переносить проект с сервера на сервер, так же упрощает обслуживание. И настройку приложения в процессе работы, не прибегая к помощи разработчиков.
Для данного проекта файл будет являтся ключничей, из него postgres будет знать с какими данными создавать пользователь/пароль/бд, а приложение будет знать с какими параметрами подключаться к ней:
POSTGRES_DB=db
POSTGRES_USER=user
POSTGRES_PASSWORD=password
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
Во время разрабтки, и работы сервера в целом, мы привыкли к тому, что все общение различных сервисов происходит через localhost
. В случае с docker-compose это не работает. Для понимания того, что произойдет после поднятия docker-compose, представьте себе локальную сеть, в которй большое количество серверов. Все сервисы запущенные на одной машиние, теперь разнесены таким образом, чтобы на каждой машине в сети работал только один сервис, то есть общение может быть только исключительно через локальную сеть, в реальной сети такое общение будет происходить с помощью ip, в docker-compose мы указываем названия сервисов.
То есть во время работы приложение и бд не будут доступны через localhost, друг для друга они будут доступны только через свои имена: todoapp, postgres.
Проверяем работу
Для запуска проекта выполните:
docker-compose up
Для проверки проекта в соседнем терминале:
curl http://localhost:8000/ -v
В ответе должна быть строка: Всё работает!
Для того, чтобы проверить связь приложения и бд, воспользуемся другой командой:
curl -H "Content-Type: application/json" http://localhost:8000/todos/ -d '{"name":"Wash the garbage","description":"Be especially thorough"}' -v
В ответ прилетит json с ID нашего todo
Чтобы проверить, что у нас всё работает, из текущей папки:
- входим в docker контейнер
docker-compose exec postgres psql -U user db
- Просим показать содержание таблицы todos
select *from todos;
В ответе видим таблицу с нашими вводными данными:
id | name | description
----+------------------+------------------------
1 | Wash the garbage | Be especially thorough
(1 row)
Docker-compose файл.
Docker-compose - инструмент для совместного запуска несколких контенеров. Основой для docker-compoes является yaml-файл с настройками. Удобство заключается в том, что единожды написанный docker-compose.yml можно легко перенести с устройства на устройство.
Установка
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Третья строчка скрипта дает нам возможность использовать docker-compose от имени сисетмы, если этот команда не будет выполнена. команда docker-compose потребует указания полноценного пути расположения.
Пример написания docker-compose
Пример взят с docs.microsoft.com
version: "3.7"
services:
app:
image: node:12-alpine
#build: .
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:/app
environment:
MYSQL_HOST: mysql
MYSQL_USER: root
MYSQL_PASSWORD: secret
MYSQL_DB: todos
networks:
app_net:
mysql:
image: mysql:5.7
volumes:
- todo-mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: todos
networks:
app_net:
volumes:
todo-mysql-data:
networks:
app_net:
driver: bridge
Ключевые слова используемые в docker-compose:
Ключи | Применение |
---|---|
build | Указывает путь откуда брать Dockerfile для создания образа |
args | Указание аргументов билда которые требуются во время создания образа |
command | Переписывает CMD указанную в Dockerfile |
devices | Мапирование физических устройств в рабочий контейнер |
depends_on | Указание зависимости сервисов друг от друга. Зависимый сервис будет запускаться последний |
dns | Указанный в ручуню DNS сервер |
entrypoint | Переписывает ENTRYPOINT директиву из Dockerfile |
env_file | Добавление переменных с помощью файла переменных окружения |
environment | Явное указание переменных в контейнер |
expose | Выставление портов контейнера, они будут доступны только linked сервисам, могут быть указаны только внутренние порты. |
image | Указание образа, который будет взят для старта контейнера |
links | Связывание контейнеров разных сервисах |
logging | Настройки логирования для сервиса. |
networks | Сеть к которой будет присоденен сервис |
ports | Маирование портов из контейнера в хост систему |
volumes | Мапирование папок из хост системы в контенер |
Docker-compose cli
Сборка контенера, имеет смысл если в yaml
файле присутствует директива build
.
Можно использовать ключ --no-cache
, в таком случае игнорируются кэшированные образы.
docker-compose build
Запуск приложения. В запуск можно добавить --build
ключ, тогда docker-compose перебилдит незакешированные шаги.
docker-compose up
Docker-compose останавливает и удаляет запущенные контенеры, согласно yaml конфигурации.
То есть выполянется 2 команды docker: docker stop
и docker rm
docker-compose stop
Отображает запущенные контейнеры принадлежащие yaml файлу.
docker-compose ps
ВНИМАНИЕ! Выполенение команда, в отличии от
docker
, должно быть с в папке с yaml файлом. Командаdocker
может выполнятся из любой папки.