learning:docker
Различия
Показаны различия между двумя версиями страницы.
learning:docker [19.04.2023 14:12] – [Поля расширения (extension fields) - устранение дублирования текста конфигурации] viacheslav | learning:docker [30.07.2024 19:21] (текущий) – внешнее изменение 127.0.0.1 | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== Docker (DKA-Develop) ====== | ||
+ | [[https:// | ||
+ | Образ (image) - основа для запуска контейнеров. Образы хранятся в реестрах (registries) - публичных (типа [[https:// | ||
+ | <code bash> | ||
+ | # Добавить пользователя в группу Docker, чтобы он имел там все права: | ||
+ | sudo usermod -aG docker username | ||
+ | newgrp docker # чтобы не перезапускать машину | ||
+ | # Запустить контейнер с Ubuntu и зайти в его терминал | ||
+ | docker run -it ubuntu bash | ||
+ | # Список всех контейнеров, | ||
+ | docker ps -a | ||
+ | # Запустить остановленный контейнер | ||
+ | docker start containername | ||
+ | # Остановить | ||
+ | docker stop containername | ||
+ | # Запуск с указанием имени хоста | ||
+ | docker run -h hostname -it ubuntu bash | ||
+ | # Список запущенных контейнеров | ||
+ | docker ps | ||
+ | # Информация о контейнере | ||
+ | docker inspect containername | ||
+ | # Задать имя контейнера | ||
+ | docker run --name containername -it ubuntu bash | ||
+ | # Посмотреть изменения в контейнере | ||
+ | docker diff containername | ||
+ | # Журнал контейнера | ||
+ | docker logs containername | ||
+ | # Удалить контейнер | ||
+ | docker rm containername | ||
+ | # Удалить все остановленные контейнеры | ||
+ | docker rm -v $(docker ps -aq -f status=exited) | ||
+ | # Удалить все образы | ||
+ | docker rmi $(docker images -q) --force | ||
+ | |||
+ | # Запустить в фоне с пробросом порта хост: | ||
+ | docker run -d -p 8000:8080 apache | ||
+ | # Список образов | ||
+ | docker images | ||
+ | |||
+ | # Создать образ из контейнера | ||
+ | docker commit containername username/ | ||
+ | # Закачать образ в реестр-репозиторий | ||
+ | # Тэг можно не указывать, | ||
+ | docker push username/ | ||
+ | </ | ||
+ | |||
+ | ===== Dockerfile ===== | ||
+ | Набор инструкций для сборки образа. | ||
+ | <code yaml> | ||
+ | # Базовый образ | ||
+ | FROM ubuntu | ||
+ | # Информация о создателе | ||
+ | MAINTAINER Username < | ||
+ | # Команды для выполнения внутри контейнера | ||
+ | RUN apt update && apt install cowsay -y && ln -s / | ||
+ | # Что выполнять по умолчанию при запуске контейнера | ||
+ | ENTRYPOINT [" | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Собрать образ | ||
+ | docker build -t username/ | ||
+ | # Запустить | ||
+ | docker run username/ | ||
+ | # Если бы в Dockerfile не был указан параметр ENTRYPOINT, | ||
+ | # то запускать надо было бы так: | ||
+ | docker run username/ | ||
+ | </ | ||
+ | |||
+ | ===== Связь между контейнерами ===== | ||
+ | Например, | ||
+ | <code bash> | ||
+ | docker run --name mysqlserver -e MYSQL_ROOT_PASSWORD=123456 -d mariadb | ||
+ | </ | ||
+ | Затем нужно запустить adminer и связать его с MariaDB. | ||
+ | Параметр %%--link%% делает в /etc/hosts контейнера запись db, указывающую на контейнер mysqlserver. | ||
+ | <code bash> | ||
+ | docker run --link mysqlserver: | ||
+ | </ | ||
+ | |||
+ | Более современный вариант связи - через publish services. | ||
+ | |||
+ | ===== docker-compose ===== | ||
+ | docker-compose**.yaml** = docker-compose**.yml** | ||
+ | <code yaml> | ||
+ | # Use root/ | ||
+ | version: ' | ||
+ | |||
+ | services: | ||
+ | |||
+ | db: | ||
+ | image: mariadb | ||
+ | # | ||
+ | restart: always | ||
+ | environment: | ||
+ | MYSQL_ROOT_PASSWORD: | ||
+ | |||
+ | adminer: | ||
+ | image: adminer | ||
+ | restart: always | ||
+ | ports: | ||
+ | - 8080:8080 | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Запустить | ||
+ | docker-compose up | ||
+ | # Запуск в фоне | ||
+ | docker-compose up -d | ||
+ | # Список контейнеров, | ||
+ | docker-compose ps | ||
+ | # Собрать, | ||
+ | docker-compose build | ||
+ | # Удалить контейнер с БД (по имени сервиса) | ||
+ | docker-compose rm db | ||
+ | </ | ||
+ | Если в Windows установлен Docker toolbox, то вход в браузере через localhost не сработает, | ||
+ | <code bash> | ||
+ | docker-machine ip default | ||
+ | </ | ||
+ | |||
+ | ===== Volumes ===== | ||
+ | Назначение путям внутри контейнера локальных каталогов на хосте. Удобно тем, что при остановке или уничтожении контейнера данные остаются в целости. | ||
+ | |||
+ | Есть 3 способа указания томов: | ||
+ | |||
+ | - Объявить том при запуске контейнера.< | ||
+ | - Объявить том с помощью инструкции VOLUME в Dockerfile, например,< | ||
+ | - Объявить том в docker-compose.yml. | ||
+ | <code yaml> | ||
+ | volumes: | ||
+ | - ./ | ||
+ | - ./ | ||
+ | </ | ||
+ | |||
+ | ===== Пример (Laravel) ===== | ||
+ | Необходимо 3 сервиса: | ||
+ | |||
+ | Файл .env с переменными: | ||
+ | < | ||
+ | # Paths | ||
+ | DB_PATH_HOST=./ | ||
+ | APP_PATH_HOST=./ | ||
+ | APP_PATH_CONTAINER=/ | ||
+ | </ | ||
+ | В данном случае в папку ./blog кладётся проект, | ||
+ | |||
+ | docker-compose.yml: | ||
+ | <code yaml> | ||
+ | version: ' | ||
+ | |||
+ | services: | ||
+ | web: | ||
+ | build: ./web | ||
+ | environment: | ||
+ | - APACHE_RUN_USER=www-data | ||
+ | volumes: | ||
+ | - ${APP_PATH_HOST}: | ||
+ | ports: | ||
+ | - 8080:80 | ||
+ | working_dir: | ||
+ | db: | ||
+ | image: mariadb | ||
+ | restart: always | ||
+ | environment: | ||
+ | MYSQL_ROOT_PASSWORD: | ||
+ | volumes: | ||
+ | - ${DB_PATH_HOST}:/ | ||
+ | |||
+ | adminer: | ||
+ | image: adminer | ||
+ | restart: always | ||
+ | ports: # должны быть разными для хоста у разных сервисов | ||
+ | - 6080:8080 | ||
+ | | ||
+ | composer: | ||
+ | image: composer: | ||
+ | volumes: | ||
+ | - ${APP_PATH_HOST}: | ||
+ | working_dir: | ||
+ | command: composer install | ||
+ | </ | ||
+ | |||
+ | ./ | ||
+ | <code yaml> | ||
+ | FROM php: | ||
+ | RUN docker-php-ext-install pdo_mysql \ | ||
+ | && a2enmod rewrite | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Сборка и запуск | ||
+ | docker-compose up --build | ||
+ | # Запустить bash в сервисе-контейнере web | ||
+ | # Благодаря указанию working_dir, | ||
+ | docker-compose exec web bash | ||
+ | </ | ||
+ | |||
+ | ===== Решение проблем ===== | ||
+ | В Windows при запуске контейнера с Volume ругается на то, что нет прав. Для этого нужно зайти в настройки Docker Desktop и на вкладке Shared Drives поставить галки на нужных дисках.\\ | ||
+ | Ситуация может осложняться тем, что у пользователя нет пароля, | ||
+ | |||
+ | Решение - завести нового локального пользователя с бессрочным паролем, | ||
+ | |||
+ | ====== Get started ====== | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | <code bash> | ||
+ | ## List Docker CLI commands | ||
+ | docker | ||
+ | docker container --help | ||
+ | |||
+ | ## Display Docker version and info | ||
+ | docker --version | ||
+ | docker version | ||
+ | docker info | ||
+ | |||
+ | ## Execute Docker image | ||
+ | docker run hello-world | ||
+ | |||
+ | ## List Docker images | ||
+ | docker image ls | ||
+ | |||
+ | ## List Docker containers (running, all, all in quiet mode) | ||
+ | docker container ls | ||
+ | docker container ls --all | ||
+ | docker container ls -aq | ||
+ | |||
+ | # Containers | ||
+ | docker build -t friendlyhello . # Create image using this directory' | ||
+ | docker run -p 4000:80 friendlyhello # Run " | ||
+ | docker run -d -p 4000:80 friendlyhello | ||
+ | docker container ls # List all running containers | ||
+ | docker container ls -a # List all containers, even those not running | ||
+ | docker container stop < | ||
+ | docker container kill < | ||
+ | docker container rm < | ||
+ | docker container rm $(docker container ls -a -q) # Remove all containers | ||
+ | docker image ls -a # List all images on this machine | ||
+ | docker image rm <image id> | ||
+ | docker image rm $(docker image ls -a -q) # Remove all images from this machine | ||
+ | docker login # Log in this CLI session using your Docker credentials | ||
+ | docker tag < | ||
+ | docker push username/ | ||
+ | docker run username/ | ||
+ | |||
+ | # Services | ||
+ | docker stack ls # List stacks or apps | ||
+ | docker stack deploy -c < | ||
+ | docker service ls # List running services associated with an app | ||
+ | docker service ps < | ||
+ | docker inspect <task or container> | ||
+ | docker container ls -q # List container IDs | ||
+ | docker stack rm < | ||
+ | docker swarm leave --force | ||
+ | |||
+ | # Swarms | ||
+ | docker-machine create --driver virtualbox myvm1 # Create a VM (Mac, Win7, Linux) | ||
+ | docker-machine create -d hyperv --hyperv-virtual-switch " | ||
+ | docker-machine env myvm1 # View basic information about your node | ||
+ | docker-machine ssh myvm1 " | ||
+ | docker-machine ssh myvm1 " | ||
+ | docker-machine ssh myvm1 " | ||
+ | docker-machine ssh myvm1 # Open an SSH session with the VM; type " | ||
+ | docker node ls # View nodes in swarm (while logged on to manager) | ||
+ | docker-machine ssh myvm2 " | ||
+ | docker-machine ssh myvm1 " | ||
+ | docker-machine ls # list VMs, asterisk shows which VM this shell is talking to | ||
+ | docker-machine start myvm1 # Start a VM that is currently not running | ||
+ | docker-machine env myvm1 # show environment variables and command for myvm1 | ||
+ | eval $(docker-machine env myvm1) | ||
+ | & " | ||
+ | docker stack deploy -c < | ||
+ | docker-machine scp docker-compose.yml myvm1:~ # Copy file to node's home dir (only required if you use ssh to connect to manager and deploy the app) | ||
+ | docker-machine ssh myvm1 " | ||
+ | eval $(docker-machine env -u) # Disconnect shell from VMs, use native docker | ||
+ | docker-machine stop $(docker-machine ls -q) # Stop all running VMs | ||
+ | docker-machine rm $(docker-machine ls -q) # Delete all VMs and their disk images | ||
+ | |||
+ | </ | ||
+ | |||
+ | ====== Docker (udemy.com) ====== | ||
+ | Докер упрощает установку и запуск программ без возни с зависимостями. Это платформа, | ||
+ | |||
+ | При установке Докера ставится 2 компонента - клиент (CLI, управление) и сервер (функциональная часть). При установке Докера рекомендуется регистрация на docker.com. После установки Докера и перезагрузки нужно вбить рег. данные в запущенный Докер для доступа к Docker Cloud. | ||
+ | |||
+ | ===== 01 Dive Into Docker ===== | ||
+ | <code bash> | ||
+ | # Версия: | ||
+ | docker version | ||
+ | |||
+ | # Запустить тестовый контейнер: | ||
+ | docker run hello-world | ||
+ | </ | ||
+ | Если образа нет в локальном кэше (image cache), он скачивается автоматически из репозитория (Docker Hub). | ||
+ | |||
+ | Программы взаимодействуют с железом через ядро (kernel) путём системных запросов (system call). Контейнер - это изолированная область для запуска процессов, | ||
+ | |||
+ | Так как namespacing и cgroups - сугубо линуксовое явление, | ||
+ | |||
+ | ===== 02 Manipulating Containers with the Docker Client ===== | ||
+ | <code bash> | ||
+ | # Аргументы контейнеру | ||
+ | docker run busybox echo hi there | ||
+ | docker run busybox ls | ||
+ | # Список запущенных контейнеров | ||
+ | docker ps | ||
+ | # Список когда-либо запущенных контейнеров | ||
+ | docker ps --all | ||
+ | </ | ||
+ | |||
+ | docker run = docker create + docker start | ||
+ | <code bash> | ||
+ | docker create hello-world # создаёт контейнер и показывает его ID | ||
+ | docker start -a ID # запускает конкретный контейнер с выводом результатов | ||
+ | docker start ID # просто запускает контейнер без вывода результатов на экран. Выводится только ID запущенного контейнера. | ||
+ | docker logs ID # посмотреть вывод уже отработавшего контейнера по команде docker start ID | ||
+ | # (не в реальном времени, | ||
+ | </ | ||
+ | Запущенный однажды контейнер лежит на диске и его всегда можно вызвать по ID, но команду заменить не получится. Например, | ||
+ | <code bash> | ||
+ | docker run busybox echo hi there | ||
+ | # Если запустить | ||
+ | docker start -a ID echo bye there | ||
+ | # то ничего не получится. | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Удаление остановленных контейнеров, | ||
+ | # (образы нужно будет скачивать заново из Docker Hub) | ||
+ | docker system prune | ||
+ | </ | ||
+ | <code bash> | ||
+ | docker stop ID | ||
+ | docker kill ID | ||
+ | # Если stop не отрабатывает за 10 сек, автоматически посылается kill. | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Запуск команд внутри контейнера | ||
+ | docker exec -it ID < | ||
+ | # Например, | ||
+ | docker exec -it ID redis-cli | ||
+ | # Без ключа -it (-i -t) процесс запустится, | ||
+ | # -i - STDIN, -t - вывод текста. Можно запустить и | ||
+ | docker exec -i ID redis-cli | ||
+ | # но в этом случае не будет выводиться консоль и будет показываться | ||
+ | # только ввод пользователя, | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Запустить " | ||
+ | docker exec -it ID sh | ||
+ | # потом можно запускать redis-cli и всё остальное за один сеанс, чтобы не вводить каждый раз | ||
+ | docker exec -i ID redis-cli | ||
+ | |||
+ | # Создать контейнер и запустить там консоль | ||
+ | docker run -it busybox sh | ||
+ | </ | ||
+ | |||
+ | Файловые системы разных контейнеров изолированы, | ||
+ | |||
+ | ===== 03 Building Custom Images Through Docker Server ===== | ||
+ | Для создания собственного образа нужно написать Dockerfile, который через клиент передаётся серверу, | ||
+ | |||
+ | Докерфайл пишется так: | ||
+ | - Указывается базовый образ (типа выбора ОС) | ||
+ | - Запускаются команды для установки доп. программ (типа скачивания инсталлятора и установки, | ||
+ | - Указываются команды, | ||
+ | |||
+ | Создаётся каталог, | ||
+ | < | ||
+ | FROM alpine | ||
+ | RUN apk add --update redis | ||
+ | CMD [" | ||
+ | </ | ||
+ | |||
+ | Затем запускается | ||
+ | <code bash> | ||
+ | docker build . | ||
+ | </ | ||
+ | На каждом этапе сборки создаётся промежуточный контейнер, | ||
+ | Если добавить команду на 2 этап, например, | ||
+ | < | ||
+ | RUN apk add --update gcc | ||
+ | </ | ||
+ | то предыдущие команды уже не будут выполняться, | ||
+ | |||
+ | <code bash> | ||
+ | # Чтобы задать человеческое имя образу при сборке: | ||
+ | docker build -t YourDockerID/ | ||
+ | # Например, | ||
+ | docker build -t username/ | ||
+ | # Версия latest грузится и запускается Докером по умолчанию. | ||
+ | # Если просто написать | ||
+ | docker build -t username/ | ||
+ | # то версия latest добавится автоматически. | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Можно сделать образ руками, | ||
+ | docker run -it alpine sh | ||
+ | apk add --update redis | ||
+ | # Из другой консоли: | ||
+ | docker ps # (узнать ID изменяемого контейнера) | ||
+ | docker commit -c 'CMD [" | ||
+ | # Создастся образ с новым ID. | ||
+ | </ | ||
+ | <WRAP round tip 75%> | ||
+ | Чтобы запустить образ, можно не копировать весь ID, достаточно части, которая будет уникальной. | ||
+ | </ | ||
+ | |||
+ | ===== 04 Making Real Projects with Docker ===== | ||
+ | Задача: | ||
+ | Функционал состоит из package.json | ||
+ | < | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | и index.js | ||
+ | <code javascript> | ||
+ | const express = require(' | ||
+ | |||
+ | const app = express(); | ||
+ | |||
+ | app.get('/', | ||
+ | res.send(' | ||
+ | }); | ||
+ | |||
+ | app.listen(8080, | ||
+ | console.log(' | ||
+ | }); | ||
+ | </ | ||
+ | Dockerfile: | ||
+ | < | ||
+ | # FROM alpine - не сработает, | ||
+ | FROM node:alpine # это вариант (тэг) alpine установки образа node, где npm есть | ||
+ | # RUN npm install - не сработает, | ||
+ | # поэтому сначала надо их скопировать туда | ||
+ | COPY ./ ./ # копирование в контексте сборочного каталога. В данном случае - скопировать все файлы | ||
+ | RUN npm install # теперь можно запускать установку | ||
+ | CMD [" | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Собрать: | ||
+ | docker build -t username/ | ||
+ | # Запуск: | ||
+ | docker run username/ | ||
+ | </ | ||
+ | Но localhost: | ||
+ | Для этого нужно запустить контейнер так: | ||
+ | <code bash> | ||
+ | docker run -p 8080:8080 username/ | ||
+ | </ | ||
+ | |||
+ | COPY ./ ./ бросает файлы в корень файловой системы контейнера, | ||
+ | WORKDIR /usr/app | ||
+ | и все дальнейшие команды будут выполняться в контексте указанного каталога. | ||
+ | |||
+ | Есть нюанс: если изменить что-либо в коде index.js и запустить пересборку образа, | ||
+ | < | ||
+ | COPY ./ | ||
+ | RUN npm install | ||
+ | COPY ./ ./ | ||
+ | </ | ||
+ | Это предоствратит постоянную инсталляцию с нуля зависимостей npm при пересборке. | ||
+ | |||
+ | ===== 05 Docker Compose with Multiple Local Containers ===== | ||
+ | Задача: | ||
+ | |||
+ | Так как два контейнера должны взаимодействовать между собой, нужно их соответственно настроить, | ||
+ | |||
+ | Docker-compose использует конфиг docker-compose.yml, | ||
+ | <code yaml> | ||
+ | version: ' | ||
+ | services: | ||
+ | | ||
+ | image: ' | ||
+ | | ||
+ | build . | ||
+ | ports: | ||
+ | - " | ||
+ | </ | ||
+ | docker-compose автоматически открывает сетевой доступ между контейнерами, | ||
+ | |||
+ | В качестве хоста в index.js нужно указывать название сервиса, | ||
+ | <code javascript> | ||
+ | host: ' | ||
+ | port: 6379 | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Запуск: | ||
+ | docker-compose up # = docker run myimage | ||
+ | docker-compose up -d # (запуск в фоне) | ||
+ | # Сборка и запуск | ||
+ | docker-compose up --build # = docker build . + docker run myimage | ||
+ | # Остановка (всех контейнеров) | ||
+ | docker-compose down | ||
+ | </ | ||
+ | |||
+ | Автоперезапуск контейнера при падении\\ | ||
+ | Варианты перезапуска: | ||
+ | * no - не перезапускать (по умолчанию) | ||
+ | * always - всегда перезапускать | ||
+ | * on-failure - перезапускать в случае ошибки (код возврата не 0) | ||
+ | * unless-stopped - всегда перезапускать, | ||
+ | |||
+ | Добавляется в docker-compose.yml в параметры конкретного сервиса. | ||
+ | <code yaml> | ||
+ | restart: always | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Статус контейнеров docker-compose | ||
+ | docker-compose ps | ||
+ | </ | ||
+ | показывает статус контейнеров, | ||
+ | |||
+ | ===== 06 Creating a Production-Grade Workflow ===== | ||
+ | Этапы развития ПО - разработка, | ||
+ | Создаётся 2 файла: Dockerfile.dev (для разработки) и просто Dockerfile (продакшн).\\ | ||
+ | Вызвать Dockerfile.dev можно так: | ||
+ | <code bash> | ||
+ | docker build -f Dockerfile.dev . | ||
+ | </ | ||
+ | |||
+ | Volume - ссылки изнутри контейнера на ресурсы вовне, например, | ||
+ | <code bash> | ||
+ | docker run -p 3000:3000 -v / | ||
+ | </ | ||
+ | **$(pwd):/ | ||
+ | **-v / | ||
+ | |||
+ | Чтобы избежать излишней сложности запуска контейнеров через docker run, можно использовать docker-compose. В docker-compose.yml нужно указать: | ||
+ | <code yaml> | ||
+ | version: ' | ||
+ | services: | ||
+ | web: | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | ports: | ||
+ | - " | ||
+ | volumes: | ||
+ | - / | ||
+ | - .:/app | ||
+ | </ | ||
+ | и запустить docker-compose up. Секция build содержит опции context: и dockerfile:, | ||
+ | |||
+ | После того, как создан Volume, который смотрит из контейнера на хост, возникает вопрос, | ||
+ | |||
+ | Тестирование: | ||
+ | <code bash> | ||
+ | docker build -f Dockerfile.dev . | ||
+ | # запустить | ||
+ | docker run -it ID npm run test | ||
+ | </ | ||
+ | Тесты в данном случае находятся в src/ | ||
+ | <code bash> | ||
+ | docker exec -it ID npm run test | ||
+ | </ | ||
+ | Можно применять это как временное решение, | ||
+ | |||
+ | Есть ещё один способ - добавить сервис для тестирования в docker-compose.yml | ||
+ | <code yaml> | ||
+ | services: | ||
+ | | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | volumes: | ||
+ | - / | ||
+ | - .:/app | ||
+ | command: [" | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Далее нужно пересобрать и запустить контейнеры | ||
+ | docker-compose up --build | ||
+ | </ | ||
+ | После этого можно менять файл тестов и видеть, | ||
+ | <code bash> | ||
+ | # Вывод процесса в контейнере на стандартный вывод, т. е. экран, не помогает. | ||
+ | docker attach -it ID | ||
+ | </ | ||
+ | Это связано с тем, что процесс запускается отдельным потоком, | ||
+ | <code bash> | ||
+ | docker exec -it ID sh | ||
+ | # и там выполнив команду | ||
+ | ps | ||
+ | </ | ||
+ | |||
+ | ==== Продакшен ==== | ||
+ | Замена движка на nginx. Вопрос в том, что в данном случае нужно использовать ДВА исходных образа - node и nginx, который нужно добавить после сборки npm. Dockerfile: | ||
+ | < | ||
+ | #Build phase | ||
+ | FROM node:alpine as builder | ||
+ | WORKDIR '/ | ||
+ | COPY package.json . | ||
+ | RUN npm install | ||
+ | COPY . . | ||
+ | RUN npm run build | ||
+ | # всё барахло (результат сборки) теперь находится в /app/build | ||
+ | |||
+ | # Run phase | ||
+ | FROM nginx | ||
+ | # копировать из builder (пред. стадии), | ||
+ | # из каталога с барахлом в стандартный каталог nginx | ||
+ | COPY --from=builder /app/build / | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Собрать образ для продакшена: | ||
+ | docker build . | ||
+ | # Запустить: | ||
+ | docker run -p 8080:80 ID | ||
+ | </ | ||
+ | |||
+ | ===== 07 Continuous Integration and Deployment with AWS ===== | ||
+ | Теперь с задействованием Гитхаба - двух веток feature и master. Master делает pull request из feature. Код проверяется Travis CI, который при новых коммитах также делает pull request кода и запускает проверки. | ||
+ | Сначала нужно создать открытый пустой репозиторий на Гитхабе. Затем | ||
+ | < | ||
+ | git init | ||
+ | git add . | ||
+ | git commit -m " | ||
+ | </ | ||
+ | Содержимое каталога скопируется. | ||
+ | < | ||
+ | git remote add origin <github repo link> | ||
+ | </ | ||
+ | |||
+ | travis-ci.org, | ||
+ | |||
+ | Настройки тревиса буду указаны в файле .travis.yml, | ||
+ | Схема файла - копировать запущенный докер, построить образ из Dockerfile.dev, | ||
+ | |||
+ | <code yaml> | ||
+ | sudo: required | ||
+ | services: | ||
+ | - docker | ||
+ | |||
+ | before_install: | ||
+ | - docker build -t username/ | ||
+ | |||
+ | script: | ||
+ | - docker run username/ | ||
+ | </ | ||
+ | -- --coverage нужен, чтобы после прохождения тестов скрипт выходил, | ||
+ | Затем выполняем | ||
+ | < | ||
+ | git add . | ||
+ | git commit -m "added travis file" | ||
+ | git push origin master | ||
+ | </ | ||
+ | После этого коммит проваливается в Гит и забирается Тревисом, | ||
+ | |||
+ | Далее идём в AWS и ищем там Elastic beanstalk, создать приложение, | ||
+ | |||
+ | Затем нужно добавить в .travis.yml | ||
+ | <code yaml> | ||
+ | deploy: | ||
+ | | ||
+ | | ||
+ | app: " | ||
+ | env: " | ||
+ | | ||
+ | | ||
+ | on: | ||
+ | branch: master | ||
+ | </ | ||
+ | |||
+ | Затем на Амазоне надо добавить IAM - ключи для доступа и права для пользователя, | ||
+ | В .travis.yml в раздел deploy затем нужно добавить | ||
+ | <code yaml> | ||
+ | access_key_id: | ||
+ | secret_access_key: | ||
+ | | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | git add . | ||
+ | git commit -m "added travis deploy config" | ||
+ | git push origin master | ||
+ | </ | ||
+ | |||
+ | Чтобы пробросить порт из контейнера в случае использования elastic-beanstalk, | ||
+ | < | ||
+ | EXPOSE 80 | ||
+ | </ | ||
+ | |||
+ | Потом опять та же мантра: | ||
+ | < | ||
+ | git add . | ||
+ | git commit -m "added expose 80" | ||
+ | git push origin master | ||
+ | </ | ||
+ | |||
+ | ===== 09 Dockerizing Multiple Services ===== | ||
+ | Сервис состоит из нескольких компонентов - самого приложения (подпапки client, api и worker), Postgres и Redis. | ||
+ | Dockerfile подпапок client, api и worker: | ||
+ | < | ||
+ | FROM node:alpine | ||
+ | WORKDIR '/ | ||
+ | COPY ./ | ||
+ | RUN npm install | ||
+ | COPY . . | ||
+ | CMD [" | ||
+ | </ | ||
+ | Docker-compose.yml в корне: | ||
+ | <code yaml> | ||
+ | version: ' | ||
+ | services: | ||
+ | # просто добавляем соответствующие контейнеры последних версий | ||
+ | | ||
+ | image: ' | ||
+ | | ||
+ | image: ' | ||
+ | api: | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | volumes: | ||
+ | - / | ||
+ | - ./api:/app # скопировать в /app контейнера содержимое ./server | ||
+ | # Следующая секция - переменные (configuration variables). | ||
+ | # Переменные задают параметры контейнера при его запуске (не при создании образа). | ||
+ | # В примере параметры хранятся в файле ./ | ||
+ | # там всякие настройки базы, адреса хостов и порты, пароли и т. п. | ||
+ | # Есть два способа задать значение переменной: | ||
+ | # variableName=value - жёстко задать значение | ||
+ | # variableName - взять значение с хоста | ||
+ | environment: | ||
+ | - REDIS_HOST=redis # в данном случае, | ||
+ | - REDIS_PORT=6379 | ||
+ | # и т. д. | ||
+ | |||
+ | | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | volumes: | ||
+ | - / | ||
+ | - ./ | ||
+ | | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | volumes: | ||
+ | - / | ||
+ | - ./ | ||
+ | </ | ||
+ | |||
+ | Далее нужно добавить nginx как редиректор разных URL в разные сервисы. Это нужно, чтобы не плодить порты доступа в контейнеры этих сервисов. На примере nginx - настройки в файле default.conf: | ||
+ | * Указать upstream-сервер client:3000 | ||
+ | * Указать upstream-сервер server:5000 | ||
+ | * Слушать порт 80 | ||
+ | * Если кто приходит на /, слать на client upstream | ||
+ | * Если кто приходит на /api, слать на server upstream | ||
+ | |||
+ | Нужно создать в проекте папку nginx, а в ней - default.conf: | ||
+ | < | ||
+ | upstream client { | ||
+ | server client: | ||
+ | } | ||
+ | |||
+ | upstream api { | ||
+ | server api:5000; | ||
+ | } | ||
+ | |||
+ | server { | ||
+ | listen 80; | ||
+ | |||
+ | | ||
+ | proxy_pass http:// | ||
+ | } | ||
+ | |||
+ | # Починить ругань на websockets, | ||
+ | # которые обращаются на / | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | | ||
+ | rewrite /api/(.*) /$1 break; | ||
+ | proxy_pass http://api; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Дальше нужно создать Dockerfile в папке ./nginx: | ||
+ | < | ||
+ | FROM nginx | ||
+ | WORKDIR '/ | ||
+ | COPY ./ | ||
+ | </ | ||
+ | |||
+ | Добавить в Docker-compose.yml сервис nginx: | ||
+ | <code yaml> | ||
+ | | ||
+ | restart: always | ||
+ | build: | ||
+ | | ||
+ | | ||
+ | ports: | ||
+ | - 3050:80 | ||
+ | </ |