notes/docker.md

1487 lines
60 KiB
Markdown
Raw Normal View History

2022-05-07 22:12:11 +03:00
###### top
## Docker - справка
***
[Базовые понятия Docker](#part1)
- [Управление контейнерами](#chapter1)
- [Логи и статистика работы](#chapter2)
- [Команды в контейнере](#chapter3)
[Docker image](#part2)
- [Общие данные](#chapter4)
- [Dockerfile](#chapter5)
- [Создание образа](#chapter6)
[Сеть в Docker](#part3)
- [Устройство сети](#chapter7)
- [Драйвер bridge](#chapter8)
- [Проброс портов](#chapter9)
- [Драйвера host и null](#chapter10)
- [DNS](#chapter11)
[Docker volumes](#part4)
- [Устройство и типы volumes](#chapter12)
- [Использование volumes](#chapter13)
- [Volume в Dockerfile](#chapter14)
- [bind mounts](#chapter15)
- [tmpfs](#chapter16)
- [Копирование данных](#chapter17)
[Docker compose](#part5)
- [YAML](#chapter18)
- [Простой конфиг](#chapter19)
- [Профили](#chapter20)
- [Запуск отдельных сервисов](#chapter21)
- [Переменные окружения](#chapter22)
- [Объединение конфигураций](#chapter23)
- [](#chapter24)
- [](#chapter25)
- [](#chapter26)
- [](#chapter27)
- [](#chapter28)
- [](#chapter29)
- [](#chapter30)
***
`docker --help`
***
###### part1
## Базовые понятия Docker
[вверх](#top)
###### Chapter1
### Управление контейнерами
`docker run nginx` - создать и запустить контейнер из образа nginx, если образа нет локально, образ будет скачан из репозитория.
`docker run --name my-nginx -d nginx` - создать и запустить контейнер с указанным именем `--name my-nginx`; в фоновом процессе `-d` - detach; из образа nginx
*кроме этого есть команды:*
`create` - создать контейнер, не запуская
`start`, `stop`, `pause`
`docker ps` - показать все запущенные контейнеры
`docker ps -a` - показать все контейнеры, в том числе остановленные
`docker rm nginx` - удалить остановленный контейнер с именем nginx
`docker rm -f nginx` - удалить контейнер с именем nginx принудительно, даже если он запущен
`docker container prune` - удалить все остановленные контейнеры
[вверх](#top)
***
###### Chapter2
### Логи и статистика работы
`docker stats` - статистика по используемым ресурсам запущенных контейнеров
```bash
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
6ed9807997de my-web 0.00% 3.348MiB / 1.941GiB 0.17% 1.22kB / 0B 0B / 16.4kB 3
08d3dc4c1595 mongo 0.22% 147.2MiB / 1.941GiB 7.41% 1.51kB / 0B 3.1MB / 43.9MB 33
^C
```
`docker inspect` - информация о контейнере или локальном образе
*можно получить выдержку из состояния, использовав ключ `-f` - format*
```bash
da2001@us:~$ docker inspect my-web -f '{{.State.Status}}'
running
```
***форматирование и фильтрация вывода доступна во многих командах, например***
```bash
da2001@us:~$ docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
```
*или*
```bash
da2001@us:~$ docker ps --help
Usage: docker ps [OPTIONS]
List containers
Options:
-a, --all Show all containers (default shows just running)
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print containers using a Go template
-n, --last int Show n last created containers (includes all states) (default -1)
-l, --latest Show the latest created container (includes all states)
--no-trunc Don't truncate output
-q, --quiet Only display container IDs
-s, --size Display total file sizes
```
```bash
da2001@us:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ed9807997de nginx "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 80/tcp my-web
08d3dc4c1595 mongo "docker-entrypoint.s…" About an hour ago Up About an hour 27017/tcp mongo
```
```bash
da2001@us:~$ docker ps --filter
ancestor= exited= health= is-task= name= publish= status=
before= expose= id= label= network= since= volume=
```
```bash
da2001@us:~$ docker ps --filter name=my-web
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ed9807997de nginx "/docker-entrypoint.…" About an hour ago Up About an hour 80/tcp my-web
```
**Логи**
`docker logs my-web` - показать логи контейнера
`docker logs my-web | grep 'default.conf'` - вывести логи и отфильтровать по сочетанию `default.conf`
`docker logs my-web | grep 'default.conf' -A 2` - строка соответствующая сочетанию `default.conf` + 2 строки после
`docker logs my-web | grep 'default.conf' -B 2` - строка соответствующая сочетанию `default.conf` + 2 строки перед
`docker logs my-web -f` - отображать логи в реальном времени
[вверх](#top)
***
###### Chapter3
### Команды в контейнере
```bash
da2001@us:~$ docker exec --help
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a container
-e, --env list Set environment variables
--env-file list Read in a file of environment variables
-i, --interactive Keep STDIN open even if not attached
--privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
-w, --workdir string Working directory inside the container
```
*В контейнере `mongo` перейти в директорию `/root` и выполнить команду `pwd`*
```bash
da2001@us:~$ docker exec -w /root mongo pwd
/root
```
*Задать переменную в контейнере и вывести список всех переменных окружения, доступных в контейнере*
```bash
da2001@us:~$ docker exec -e MYVAR=1 mongo printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=08d3dc4c1595
GOSU_VERSION=1.12
JSYAML_VERSION=3.13.1
MONGO_PACKAGE=mongodb-org
MONGO_REPO=repo.mongodb.org
MONGO_MAJOR=5.0
MONGO_VERSION=5.0.3
MYVAR=1
HOME=/root
```
*Покдлючиться к оболочке контейнера в интерактивном режиме*
```bash
da2001@us:~$ docker exec -it mongo bash
root@08d3dc4c1595:/#
```
*Выполнить в контейнере команду `mongo --version`*
```bash
da2001@us:~$ docker exec mongo mongo --version
MongoDB shell version v5.0.3
Build Info: {
"version": "5.0.3",
"gitVersion": "657fea5a61a74d7a79df7aff8e4bcf0bc742b748",
"openSSLVersion": "OpenSSL 1.1.1f 31 Mar 2020",
"modules": [],
"allocator": "tcmalloc",
"environment": {
"distmod": "ubuntu2004",
"distarch": "x86_64",
"target_arch": "x86_64"
}
}
```
`docker exec mongo mongo --version > ver.txt` - перенаправить вывод в файл на хосте
`docker exec mongo bash -c 'mongo --version > ver.txt'` - перенаправить вывод в файл в контейнере
[вверх](#top)
***
###### part2
## Docker image
[вверх](#top)
###### Chapter4
### Общие данные
`docker image --help`
`docker images` - показать скачанные образы
`docker save --output nginx.tar nginx` - сохранить образ в текущую директорию
`docker image import --help` - импорт ранее сохранённого образа
`docker history nginx` - информация о создании образа
`docker inspect nginx` - информация об образе
`docker pull nginx` - скачать образ nginx не запуская контейнер
`docker push --help` - опубликовать созданный образ во внешнем реестре образов
*`ls` - аналог `docker images`*
```bash
da2001@us:~$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mongo latest fefd78e9381a 12 days ago 699MB
nginx latest 87a94228f133 2 weeks ago 133MB
```
*вывести определённую колонку, название колонки с **большой** буквы*
```bash
da2001@us:~$ docker image ls --format {{.Tag}}
latest
latest
```
```bash
da2001@us:~$ docker image ls --format {{.Repository}}
mongo
nginx
```
*если образов много, вывод можно отфильтровать*
```bash
da2001@us:~$ docker image ls --filter
before= dangling= label= reference= since=
```
`docker image rm hello-world` - удалить образ
`docker rmi hello-world` - удалить образ
`docker image rm hello-world -f` - удалить образ даже если его использует какой-то контейнер, контейнер удалён НЕ будет
`docker image prune` - удалить все образы без тега
[вверх](#top)
***
###### Chapter5
### Dockerfile
`FROM ubuntu:20.04` - установит базовый образ, на основе которого будет создаваться текущий образ. Если тег `20.04` не указан, будет использован образ `latest`
`LABEL ENV=”DEVELOPMENT”` - пара ключ-значение, используемая для указания метаданных информации образа
`RUN apt-get update`
`RUN apt-get install tomcat` - используется для выполнения команды на базовом образе и создает новый слой
`CMD [“java”, “-jar”, “app.jar”]` - используется для задания команды, которая будет выполняться первой при запуске контейнера
`EXPOSE 8080` - откроет порт для доступа к контейнеру. Контейнер будет прослушивать этот сетевой порт
`MAINTAINER devops@admin.in` - предоставит подробную информацию об авторе, который создал этот образ
`ENV DB_NAME=”MySQL”`
`ENV DB_VERSION=”8.0”` - используется для установки переменных среды в паре ключ-значение. Эти переменные устанавливаются во время сборки образа и доступны после создания контейнера
`COPY /target/devops.jar devops.jar` - используется для копирования локальных файлов в контейнер
`ADD devops.tar.xz / .`
`ADD http://example.com/abc.git /usr/local/devops/` - работает так же, как COPY, но имеет некоторые дополнительные функции, такие например, что мы можем извлечь локальный tar и добавить удаленный URL
`ENTRYPOINT [“java”, “-jar”, “app.jar”]` - используется для установки основной команды для образа. Он работает так же, как инструкция CMD. Разница между CMD и ENTRYPOINT в том, что инструкции не перезаписываются в ENTRYPOINT
`VOLUME /app/devops` - создает точку монтирования с указанным именем
`USER <user>[:<group>]`
`USER <UID>[:<GID>]` - устанавливает имя пользователя и группу пользователей при запуске образа
`WORKDIR /var/lib/` - установит рабочий каталог. Он создаст каталог, если его нет
[вверх](#top)
***
###### Chapter6
### Создание образа
`docker build --help`
*Пример сборки образа*
```bash
docker build -f ./apps/api/Dockerfile -t test:latest .
```
`-f` - указать путь к Dockerfile, если он не в текущей директории
`-t` - указать имя образа с тегом, если тег не будет указан, по-умолчанию присвоится `:latest`
`.` - брать контекст для образа из текущей директории
[вверх](#top)
***
###### part3
## Сеть в Docker
[вверх](#top)
- `bridge` мост — это сетевой драйвер по умолчанию. Бридж сеть используется, когда приложения запускаются в автономных контейнерах, которые должны взаимодействовать между собой (Наглядный пример Nginx + MySQL);
- `host` хост — это сетевой драйвер для автономных контейнеров (удаленная сетевая изоляция между контейнером и Docker хостом). Данный драйвер доступен только для docker-swarm;
- `overlay/overlay2` оверлей (наложенная сеть), — это сетевой драйвер для соединения нескольких демонов Docker между собой и которые позволяют docker-swarm службам взаимодействовать друг с другом. Также можно использовать оверлейные сети для облегчения связи между docker-swarm и автономным контейнером или между двумя отдельными контейнерами на разных Docker демонах. Эта стратегия устраняет необходимость выполнения маршрутизации на уровне ОС между этими контейнерами;
- `macvlan` маквлан — это сетевой драйвер, который позволяют назначать MAC-адрес контейнеру, делая его отображаемым как физическое устройство в сети. Docker демон направляет трафик на контейнеры по их MAC-адресам. Использование macvlan драйвера иногда является лучшим выбором при работе с устаревшими приложениями, которые ожидают, что они будут напрямую подключены к физической сети;
- `none` — это сетевой драйвер, который умеет отключать всю сеть для контейнеров. Обычно используется в сочетании с пользовательским сетевым драйвером;
- `Network plugins` — кроме этого, можно установить и использовать сторонние сетевые плагины с Docker контейнерами. Эти плагины доступны в Docker Store или у сторонних поставщиков услуг.
###### Chapter7
### Устройство сети
```bash
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
```
*Отобразить имеющиеся сети*
```bash
da2001@us:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
222826f8b512 bridge bridge local
5f64c40ea352 host host local
79350884305f none null local
```
*Создать сеть типа `bridge` с именем `br2`*
```bash
da2001@us:~$ docker network create br2
40ff1259ca7e103736c74da0309d6fde5d8439d6844d6f5997b216912d05a705
```
или
```bash
da2001@us:~$ docker network create --driver=bridge br2
```
По-умолчанию, всегда создаётся мост
```bash
da2001@us:~$ docker network ls
NETWORK ID NAME DRIVER SCOPE
40ff1259ca7e br2 bridge local
222826f8b512 bridge bridge local
5f64c40ea352 host host local
79350884305f none null local
```
*пример создания оверлей-сети*
```bash
da2001@us:~$ docker network create --driver overlay overlay-net
```
для создания оверлей-сети необходимо активировать docker-swarm
[вверх](#top)
***
###### Chapter8
### Драйвер bridge
Сеть с драйвером bridge создаётся по-умолчанию.
Контейнеры, использующие одну сеть могут видеть друг друга по выделенному им IP адресу.
Посмотреть детальную информацию о сети можно с помощью команды `inspect`
```bash
da2001@us:~$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "222826f8b512e0803fc5d6fa26c443af23908be03f46b15f41d1a932557a9df5",
"Created": "2021-10-29T15:30:59.140332733+03:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"08d3dc4c15953ed7a25e629b983ecba977ed64f73bf3d138943bb12e644c463b": {
"Name": "mongo",
"EndpointID": "f24d0dfbe08458bc7c7c5ca31cec04832c00e3ba062f18757277033754d4e4bb",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"56e21d5c7bbdf562e75a5ee614e43648273e9960bc72678285a02863c46b2061": {
"Name": "node-1",
"EndpointID": "788fcfc6ce612363128d7b3d8c16fd259ea0bd84c0114702fefb64ec739161d6",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"6ed9807997de2bed3d6f2aeafc2fca5f2d843a55e10b1611e7f5e474f2be473d": {
"Name": "my-web",
"EndpointID": "a7d5032f4ea38edb0cf7f6f3ecbed7eada2e0cf9184dfb5c393b67cfb6f72c57",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"f4331c7520ba749fbdf33d98c1fcb5284a2df63e510f841e7dcd655878c43941": {
"Name": "node-2",
"EndpointID": "82baf3a4d8fcddd3538b86cf3237e710b53d9975a78ec98a07e3055fb7ee80a8",
"MacAddress": "02:42:ac:11:00:05",
"IPv4Address": "172.17.0.5/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
```
*в длинном выводе указана вся информация о сети, её адресации и контейнерах, которые используют эту сеть.*
***Чтобы контейнеры могли обращаться друг к другу по имени, необходимо создать новую сеть и добавить в неё эти контейнеры***
```bash
da2001@us:~$ docker network create br2
40ff1259ca7e103736c74da0309d6fde5d8439d6844d6f5997b216912d05a705
da2001@us:~/docker-demo-3$ docker run -d --name node-1 demo3
56e21d5c7bbdf562e75a5ee614e43648273e9960bc72678285a02863c46b2061
da2001@us:~/docker-demo-3$ docker run -d --name node-2 demo3
f4331c7520ba749fbdf33d98c1fcb5284a2df63e510f841e7dcd655878c43941
da2001@us:~/docker-demo-3$ docker network connect br2 node-1
da2001@us:~/docker-demo-3$ docker network connect br2 node-2
da2001@us:~/docker-demo-3$ docker network inspect br2
[
{
"Name": "br2",
"Id": "40ff1259ca7e103736c74da0309d6fde5d8439d6844d6f5997b216912d05a705",
"Created": "2021-10-31T11:20:50.595291142+03:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"56e21d5c7bbdf562e75a5ee614e43648273e9960bc72678285a02863c46b2061": {
"Name": "node-1",
"EndpointID": "9ac4317d24147360565c69e021e4c6bc7a407103c2e6a907475f707f4deed32a",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"f4331c7520ba749fbdf33d98c1fcb5284a2df63e510f841e7dcd655878c43941": {
"Name": "node-2",
"EndpointID": "3e41fd9618f71446878a7c585d9289bc4a099c7c15f8cf835084c0015c87ed54",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
```
*из вывода видно, что к сети br2 подключено 2 контейнера: node-1(172.18.0.2) и node-2(172.18.0.3)*
*подключимся к node-1 и попробуем пинговать node-2*
```bash
da2001@us:~$ docker exec -it node-1 sh
/opt/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
15: eth1@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1
valid_lft forever preferred_lft forever
/opt/app # ping 172.17.0.5
PING 172.17.0.5 (172.17.0.5): 56 data bytes
64 bytes from 172.17.0.5: seq=0 ttl=64 time=0.099 ms
64 bytes from 172.17.0.5: seq=1 ttl=64 time=0.065 ms
64 bytes from 172.17.0.5: seq=2 ttl=64 time=0.058 ms
64 bytes from 172.17.0.5: seq=3 ttl=64 time=0.058 ms
^C64 bytes from 172.17.0.5: seq=4 ttl=64 time=0.060 ms
64 bytes from 172.17.0.5: seq=5 ttl=64 time=0.057 ms
^C
--- 172.17.0.5 ping statistics ---
6 packets transmitted, 6 packets received, 0% packet loss
round-trip min/avg/max = 0.057/0.066/0.099 ms
/opt/app # ping node-2
PING node-2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.060 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.061 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.061 ms
64 bytes from 172.18.0.3: seq=3 ttl=64 time=0.067 ms
64 bytes from 172.18.0.3: seq=4 ttl=64 time=0.062 ms
^C
--- node-2 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.060/0.062/0.067 ms
/opt/app #
```
*контейнер можно создавать сразу с подключением к необходимоу сети*
```bash
da2001@us:~$ docker run -d --name node-3 --network br2 demo3
daa1712392be54aa26b8f14365d3a9cdfa13cf19ad0524afe1db352d9c3e4e77
```
[вверх](#top)
***
###### Chapter9
### Проброс портов
Для взаимодействия с приложениями внутри контейнеров из хост системы необходимо выполнить проброс портов в контейнер
```bash
da2001@us:~$ docker run -d --name node-4 --network br2 -p 2000:3000 demo3
25dfcaa0e29e7e99f2e93b45dbdbd3268b9781998215343323afceaeefff8c72
```
порт 2000 хоста пробросили на порт 3000 контейнера
```bash
da2001@us:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
25dfcaa0e29e demo3 "docker-entrypoint.s…" 2 minutes ago Up About a minute 0.0.0.0:2000->3000/tcp, :::2000->3000/tcp node-4
```
*теперь с хоста к контейнеру можно обратиться на порт 2000*
```bash
da2001@us:~$ curl localhost:2000
{"eth0":["172.18.0.5"]}
```
*при этом, порт 3000 дотсупен не будет*
```bash
da2001@us:~$ curl localhost:3000
curl: (7) Failed to connect to localhost port 3000: Connection refused
```
[вверх](#top)
***
###### Chapter10
### Драйвера host и null
Если дополнительный слой абстракции в виде сети внутри контейнера не нужен, можно создать контейнер с сетью `host`, тогда у контейнера будет IP адрес сети docker0 хоста
```bash
da2001@us:~$ docker run -d --name node-5 --network host demo3
e7ea1e790aca5e122883e994e836fae835e8b9f4bd0c02acbc0a691ed7a5a2bc
```
*посмотрим IP адрес хоста*
```bash
da2001@us:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
link/ether 8e:eb:ab:c6:9b:ff brd ff:ff:ff:ff:ff:ff
inet 192.168.13.254/24 brd 192.168.13.255 scope global dynamic ens18
valid_lft 328sec preferred_lft 328sec
inet6 fe80::8ceb:abff:fec6:9bff/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:50:59:0e:e1 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:50ff:fe59:ee1/64 scope link
valid_lft forever preferred_lft forever
```
*подключимся к контейнеру и проверим его IP*
```bash
da2001@us:~$ docker exec -it node-5 sh
/opt/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP qlen 1000
link/ether 8e:eb:ab:c6:9b:ff brd ff:ff:ff:ff:ff:ff
inet 192.168.13.254/24 brd 192.168.13.255 scope global dynamic ens18
valid_lft 328sec preferred_lft 328sec
inet6 fe80::8ceb:abff:fec6:9bff/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:50:59:0e:e1 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:50ff:fe59:ee1/64 scope link
valid_lft forever preferred_lft forever
```
***IP адреса на хосте и в контейнере идентичны***
Обратная ситуация, когда для работы контейнера сеть не нужна совсем.
*в этом случае необходимо создать контейнер с сетью `none`*
```bash
da2001@us:~$ docker run -d --name node-6 --network none demo3
9fc34160933654ac7b2ec8ec57c8de9a488de080262d836d3fd97c7ff43d26ac
```
*подключимся к контейнеру и проверим его сетевые интерфейсы*
```bash
da2001@us:~$ docker exec -it node-6 sh
/opt/app # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
```
[вверх](#top)
***
###### Chapter11
### DNS
Если необходимо в контейнере указать определённый DNS сервер, его можно передать в качестве параметра при создании контейнера
```bash
da2001@us:~$ docker run -d --name node-7 --dns 8.8.8.8 demo3
8c0e984de40f504f1a747a5c85fed2c8b7b6e8f5e8379a9bbc0da352ad77612d
da2001@us:~$ docker exec -it node-7 sh
/opt/app # cat /etc/resolv.conf
search da2001.ru
nameserver 8.8.8.8
```
[вверх](#top)
***
###### part4
## Docker volumes
[вверх](#top)
###### Chapter12
### Устройство и типы volumes
- `tmpfs` - данные хранятся внутри контейнера, доступны только в нём и цикл жизни этих данных совпадается с циклом жизни контейнера. Т.е. при остановке/удалении контейнера, данные недоступны;
- `volumes` - ***тома хранения данных, рекомендуемый разработчиками Docker способ хранения данных***. В Linux тома находятся по умолчанию в `/var/lib/docker/volumes/`. Другие программы не должны получать к ним доступ напрямую, только через контейнер.
* Тома создаются и управляются средствами Docker: командой docker volume create, через указание тома при создании контейнера в Dockerfile или docker-compose.yml.
* В контейнере том видно как обычный каталог, который мы определяем в Dockerfile. Тома могут быть с именами или без — безымянным томам Docker сам присвоит имя.
* Один том может быть примонтирован одновременно в несколько контейнеров. Когда никто не использует том, он не удаляется, а продолжает существовать. Команда для удаления томов: `docker volume prune`.
* Можно выбрать специальный драйвер для тома и хранить данные не на хосте, а на удалённом сервере или в облаке.
*<u>Для чего стоит использовать тома в Docker:</u>*
+ шаринг данных между несколькими запущенными контейнерами;
+ решение проблемы привязки к ОС хоста;
+ удалённое хранение данных;
+ бэкап или миграция данных на другой хост с Docker (для этого надо остановить все контейнеры и скопировать содержимое из каталога тома в нужное место).
- `bind mounts` - монтирование каталога хоста. Более простая концепция: файл или каталог с хоста просто монтируется в контейнер.
[вверх](#top)
***
###### Chapter13
### Использование volumes
```bash
da2001@us:~$ docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
```
*Создадим volume с именем demo*
```bash
da2001@us:~$ docker volume create demo
demo
da2001@us:~$ docker volume ls
DRIVER VOLUME NAME
local demo
```
```bash
da2001@us:~$ docker volume inspect demo
[
{
"CreatedAt": "2021-10-31T13:41:28+03:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/demo/_data",
"Name": "demo",
"Options": {},
"Scope": "local"
}
]
```
`/var/lib/docker/volumes/demo` - путь к папке с созданным томом на хосте. Данные контейнера будут храниться в папке `_data`
*сейчас эта папка пуста*
```bash
da2001@us:~$ sudo ls /var/lib/docker/volumes/demo/_data
[sudo] password for da2001:
da2001@us:~$ sudo du -hs /var/lib/docker/volumes/demo/_data
4,0K /var/lib/docker/volumes/demo/_data
```
*Создадим 2 контейнера и в качестве аргумента укажем использовать созданный том*
```bash
da2001@us:~$ docker run -d --name web-1 -v demo:/data nginx:alpine
1d0eeceefa56d2a60d4deb3c7dadfcf90b75df42e497c6dbd91546510b33ce6b
da2001@us:~$ docker run -d --name web-2 -v demo:/data nginx:alpine
eb5d5a92157e4bce9c61c8e9735b53217268fa4777354a493dca3765950a93b4
da2001@us:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eb5d5a92157e nginx:alpine "/docker-entrypoint.…" 56 seconds ago Up 54 seconds 80/tcp web-2
1d0eeceefa56 nginx:alpine "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp web-1
```
*подключимся к контейнеру `web-1` и создадим файл в папке `/data`*
```bash
da2001@us:~$ docker exec -it web-1 sh
/ # echo TEST > /data/file
/ # cat /data/file
TEST
```
*проверим наличие файла на хосте*
```bash
da2001@us:~$ sudo cat /var/lib/docker/volumes/demo/_data/file
TEST
```
*проверим доступность этого файла в контейнере `web-2` и добавим в этот файл еще одну строку*
```bash
da2001@us:~$ docker exec -it web-2 sh
/ # cat /data/file
TEST
/ # echo TEST from web-2 >> /data/file
```
*убедимся, что в контейнере `web-1` в файле также появилась новая строка*
```bash
da2001@us:~$ docker exec -it web-1 sh
/ # cat /data/file
TEST
TEST from web-2
```
*При попытке удалить том, который используется контейнерами, получим ошибку*
```bash
da2001@us:~$ docker volume rm demo
Error response from daemon: remove demo: volume is in use - [1d0eeceefa56d2a60d4deb3c7dadfcf90b75df42e497c6dbd91546510b33ce6b, eb5d5a92157e4bce9c61c8e9735b53217268fa4777354a493dca3765950a93b4]
```
*после остановки и удаления контейнеров, том удаляется без ошибок*
```bash
da2001@us:~$ docker stop web-1 web-2
web-1
web-2
da2001@us:~$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
eb5d5a92157e4bce9c61c8e9735b53217268fa4777354a493dca3765950a93b4
1d0eeceefa56d2a60d4deb3c7dadfcf90b75df42e497c6dbd91546510b33ce6b
Total reclaimed space: 2.308kB
da2001@us:~$ docker volume rm demo
demo
```
[вверх](#top)
***
###### Chapter14
### Volume в Dockerfile
Создадим свой образ на основе официального образа nginx, но добавим в Dockerfile данные о необходимом томе. Создадим том, положим в него тестовую html страницу и примонтируем том к контейнеру.
1. Создадим Dockerfile
```dockerfile
FROM nginx
WORKDIR /usr/share/nginx/html
VOLUME ["/usr/share/nginx/html"]
EXPOSE 80
```
2. Создадим том
```bash
da2001@us:~$ docker volume create web
web
```
3. Добавим в созданные том тестовую html страницу
```bash
da2001@us:~$ sudo bash -c 'echo "Welcome to static site from volume" > /var/lib/docker/volumes/web/_data/index.html'
```
4. Создадим образ на основе Dockerfile
```bash
da2001@us:~$ docker build -t my-nginx .
Sending build context to Docker daemon 145.3MB
Step 1/4 : FROM nginx
latest: Pulling from library/nginx
b380bbd43752: Pull complete
fca7e12d1754: Pull complete
745ab57616cb: Pull complete
a4723e260b6f: Pull complete
1c84ebdff681: Pull complete
858292fd2e56: Pull complete
Digest: sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Status: Downloaded newer image for nginx:latest
---> 87a94228f133
Step 2/4 : WORKDIR /usr/share/nginx/html
---> Running in 3a87fe17392b
Removing intermediate container 3a87fe17392b
---> 9637854f3611
Step 3/4 : VOLUME ["/usr/share/nginx/html"]
---> Running in f332cde38eef
Removing intermediate container f332cde38eef
---> 75291905e821
Step 4/4 : EXPOSE 80
---> Running in d5faf760b570
Removing intermediate container d5faf760b570
---> f194075a481b
Successfully built f194075a481b
Successfully tagged my-nginx:latest
```
```bash
da2001@us:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-nginx latest f194075a481b 7 seconds ago 133MB
nginx latest 87a94228f133 3 weeks ago 133MB
```
5. Создадим контейнер на основе нового образа
```bash
da2001@us:~$ docker run -d --name web-demo -v web:/usr/share/nginx/html -p 8080:80 my-nginx
97c4b627bd7a7248ffdb33e90a2ec65678a432bb68db9fa16ad27061ae625f59
```
6. Теперь убедимся, что том подключился к контейнеру и тестовая html страница доступна из контейнера
```bash
da2001@us:~$ curl localhost:8080
Welcome to static site from volume
```
[вверх](#top)
***
###### Chapter15
### bind mounts
`bind mounts` - позволяет примонтировать папку/файл из хостовой системы в контейнер
Пример: создадим в текущей директории хоста папку `html` и положим в неё файл `index.html`
```bash
da2001@us:~$ mkdir html
da2001@us:~$ echo 'Start page from bind mounts' > html/index.html
```
Теперь запустим контейнер и примонтируем в него созданную папку
```bash
da2001@us:~$ docker run -d --name web-2 -v /home/da2001/html:/usr/share/nginx/html -p 8080:80 nginx
ddeefdec9653793acb01b2c25ee412fb60a7b5cdb42330d211113c3e299d6c1d
```
Проверим работу nginx запущенного контейнера - должна открыться созданная ранее html страница
```bash
da2001@us:~$ curl localhost:8080
Start page from bind mounts
```
[вверх](#top)
***
###### Chapter16
### tmpfs
`tmpfs` - указанные данные этого типа существуют только пока контейнер работает, после остановки контейнера данные удаляются
Для монтирования можно использовать 2 вида записи
```bash
da2001@us:~$ docker run -d --name demo --tmpfs /vardir -p 8080:80 nginx
````
или
```bash
da2001@us:~$ docker run -d --name demo --mount type=tmpfs,dectination=/vardir -p 8080:80 nginx
```
*второй тип записи применим и для других типов монтирования*
[вверх](#top)
***
###### Chapter17
### Копирование данных
Если возникает необходимость скопировать какие-то данные в контейнер или из него, можно воспользоваться командой `docker cp`
```bash
da2001@us:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ddeefdec9653 nginx "/docker-entrypoint.…" 20 minutes ago Up 20 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp web-2
```
*скопировать папку html хоста в папку html в контейнере*
```bash
da2001@us:~/html$ docker cp /home/da2001/html web-2:/usr/share/nginx/html
```
*скопировать содержимое папки html хоста в папку html в контейнере*
```bash
da2001@us:~/html$ docker cp /home/da2001/html/. web-2:/usr/share/nginx/html
```
*обратная задача - скопировать данные из контейнера на хост*
```
da2001@us:~/html$ docker cp web-2:/usr/share/nginx/html /home/da2001/html
```
[вверх](#top)
***
###### part5
## Docker compose
[вверх](#top)
###### Chapter18
### YAML
`yaml` - считается наиболее удобным для восприятия человеком среди подобных форматов: yaml, xml, json.
В основе лежит принцип ключ: значение и отступы для создания структуры подчинённости.
Стандартный размер отступа - 2 пробела.
```yaml
# comment
# text
name: test
name2: "test \n"
name3: 'test 234'
# digit
age: 35
version: 2.3
```
Логические значения могут быть заданы тремя равнозначными способами
```yaml
# boolean
isDev: True
isDev2: False
isDev3: on
isDev4: off
isDev5: yes
isDev6: no
```
Описание объектов
```yaml
user:
name: Василий
age: 25
position: engineer
```
Списки
```yaml
users:
- name: Дмитрий
age: 34
position: administrator
- name: Анна
age: 24
position: accountant
```
*альтернативная запись списков без отступов*
```yaml
users:
- name: Дмитрий
age: 34
position: administrator
- name: Анна
age: 24
position: accountant
```
*списки без ключей*
```yaml
users:
- Николай
- Андрей
```
*описание списков в виде json*
```yaml
versions: [1.7, 2.3, 'latest']
```
Описание строк
*многострочная строка*
```yaml
multiline: |
Эта строка сохранит своё
форматирование и будет
отображаться в несколько строк
```
*длинная строка без переноса*
```yaml
singleline: >
Это очень длинная строка,
но она будет отображена без
использования переносов
```
Если в рамках одного yaml файла необходимо описать несколько независимых сущностей, их можно отделить друг от друга с помощью `---`
[вверх](#top)
***
###### Chapter19
### Пример файла docker-compose.yml
```yaml
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
depends_on:
- db
environment:
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: db_user
WORDPRESS_DB_PASSWORD: wp_db_pass
volumes:
["./:/var/www/html"]
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: wp_db
MYSQL_USER: db_user
MYSQL_PASSWORD: wp_db_pass
MYSQL_ROOT_PASSWORD: db_root_pass
volumes:
- db:/var/lib/mysql
volumes:
db:
```
Эта конфигурация запустит 2 контенера: mysql и wordpress
**Разбор параметров**
`version: '3.1'` - в зависимости от используемой версии, compose может принимать или нет некоторые директивы, также зависит от установленной версии docker
*Зависимость версии compose от версии docker указана в таблице на сайте с документацией. Также объясняются возможные директивы, которые могут быть описаны в файле docker-compose.yml*
[*>> документация по compose <<*](https://docs.docker.com/compose/compose-file/compose-file-v3/)
*Каждая директива может быть описана в краткой и полной форме. Формы записи равнозначны, полная запись может быть проще для восприятия, но длиннее в записи. В данном примере будет рассмотрена краткая форма описания.*
`services:` - из названия понятно, что в этой секции описаны используемые сервисы. Указаны образы, на основе которых будут запущены контейнеры и параметры запуска: хранилища, сеть, переменные и пр.
`wordpress:` - произвольное название сервиса, который собираемся запустить
`image:` - указан образ, на основе которого будет запущен контейнер. Может быть указан с конкретной версией `mysql:5.7`, `wordpress:latest`, так и без указания версии `wordpress`, в этом случае будет подставлен тег `latest`
`restart:` - опция перезапуска контейнера. Может принимать значения: `"no"`, `always`, `on-failure`, `unless-stopped`. Игнорируется при запуске в swarm.
`ports:` - проброс портов. В данном примере - на порт 8080 хоста будет проброшен порт 80 контейнера.
`depends_on:` - зависимость при запуске. Если параметр указан, контейнер этой секции будет запущен после того, который указан в параметре. В данном примере - `wordpress` будет запущен только после успешного запуска `db`.
`environment:` - переменные, которые необходимо передать в контейнер в формате `ключ: значение`. Необходимые переменные для успешного запуска, обычно указаны на странице описания образа в docker hub.
`volumes:` - в секции services описывает тома, которые будут использованы в контейнере. В контейнер можно подключить созданный в docker том или выполнить монтирование директории или отдельного файла из хоста. Используется, когда необходимо сохранить данные после остановки/удаления контейнера, например базу данных, конфигурационные файлы, контент сайта и т.д.
`volumes:` - в отдельной секции описывает название томов, которые необходимо создать посредством docker для использования в контейнерах.
В данном примере не описано, но часто применяется на практике:
`networks:` - в секции services описывает сеть, к которой должен подключиться контейнер, если секция указана, её необходимо обязательно создать.
Кроме ситуации, в которой контейнеру запрещается использовать сеть:
```yaml
app:
build: ./app
networks:
- none
```
или когда используется сеть хоста
```yaml
app:
build: ./app
networks:
- host
```
`networks:` - в отдельной секции описывает сети, которые необходимо создать для использования в контейнерах. Для режимов сети без дополнительных плагинов, используются три драйвера: `bridge` - контейнерам выделяются IP адреса из одной подсети, `host` - контейнеры используют сеть хоста, `none` - контейнеры не используют сеть.
[вверх](#top)
***
###### Chapter20
### Профили
Иногда возникают ситуации, когда при запуске compose нет необходимости стартовать все сервисы, например, в целях тестирования или отладки. В таких ситуациях можно создать профили и добавить необходимые сервисы в эти профили. В этом случае, compose можно запускать явно указав какие профили необходимо запустить.
```yaml
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
profile:
- wordpress_1
```
Теперь, чтобы запустить контейнер с указанным профилем, его необходимо явно указать при запуске
```bash
da2001@us:~/wp$ docker-compose --profile wordpress_1 up -d
```
*этой командой будут запущены контейнеры у которых указан профиль `wordpress_1` и не указан профиль вообще.*
Если необходимо запустить контейнеры с несколькими профилями, каждый необходимо отдельно указать
```bash
da2001@us:~/wp$ docker-compose --profile wordpress_1 --profile database up -d
```
Кроме этого, может встречаться и другая запись, когда перед стартом через запятую передаются все необходимые профили в виде переменных окружения
```bash
da2001@us:~/wp$ COMPOSE_PROFILES=wordpress_1 docker-compose up -d
```
Стоит иметь ввиду, если один сервис зависит от другого - указана директива `depends_on`, нужно внимательно использовать профили. Например, если взять предыдущий пример compose и добавить в секцию сервиса `db` профиль, а в секции сервиса `wordpress` профиль указан не будет:
```yaml
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
depends_on:
- db
db:
image: mysql:5.7
restart: always
profile:
- database
```
команда `docker-compose up -d` завершится ошибкой, т.к. при таком запуске будут стартовать только контейнеры без указанного профиля, а в этом примере - контейнер без профиля зависит от успешного запуска контейнера с указанным профилем.
[вверх](#top)
***
###### Chapter21
### Запуск отдельных сервисов
При использовании compose можно запустить отдельные сервисы явно указав это в команде запуска
```bash
da2001@us:~/wp$ docker-compose run wordpress -d
```
*НО, в нашем примере будут запущены оба контейнера, т.к. запуск wordpress зависит от успешного запуска db*
Кроме этого стоит брать во внимание особенности запуска при использовании профилей.
[вверх](#top)
***
###### Chapter22
### Переменные окружения
Переменные окружения удобно использовать для передачи значений в запускаемые контейнеры, например для указания имён контейнеров или передачи значений имени, пароля, названия базы данных и пр.
По-умолчанию, compose считывает значения из файла `.env`, находящегося в той же директории что и `docker-compose.yml`.
Например:
```bash
da2001@us:~/wp$ cat .env
wp_container_name=wp
db_container_name=db
db_name=wp_db
db_root_pass=db_root_pass
db_user=db_user
db_pass=wp_db_pass
```
```bash
da2001@us:~/wp$ cat docker-compose.yml
version: '3.1'
services:
wordpress:
image: wordpress
container_name: "${wp_container_name}"
restart: always
ports:
- 8080:80
depends_on:
- db
environment:
WORDPRESS_DB_NAME: "${db_name}"
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: "${db_user}"
WORDPRESS_DB_PASSWORD: "${db_pass}"
volumes:
- wp:/var/www/html
db:
image: mysql:5.7
container_name: "${db_container_name}"
restart: always
environment:
MYSQL_DATABASE: "${db_name}"
MYSQL_USER: "${db_user}"
MYSQL_PASSWORD: "${db_pass}"
MYSQL_ROOT_PASSWORD: "${db_root_pass}"
volumes:
- db:/var/lib/mysql
volumes:
db:
wp:
```
Если файл с описанием переменных называется не `.env`, тогда при запуске compose нужно это явно указать
```bash
da2001@us:~/wp$ docker-compose --env-file .env-web up -d
```
Также можно указать для каждого сервиса свой файл с переменными окружения и указать в нём необходимые имена и значения переменных
```bash
da2001@us:~/wp$ cat docker-compose.yml
version: '3.1'
services:
wordpress:
image: wordpress
container_name: "${wp_container_name}"
restart: always
ports:
- 8080:80
depends_on:
- db
env_file:
- .env-wp
volumes:
- wp:/var/www/html
db:
image: mysql:5.7
container_name: "${db_container_name}"
restart: always
env_file:
- .env-db
volumes:
- db:/var/lib/mysql
volumes:
db:
wp:
```
Перед запуском compose будет полезным посмотреть верно ли подставились переменные, для этого используется следующая команда:
```bash
docker-compose config
```
или если указано своё имя для файла с переменными
```bash
docker-compose --env-file .env-web config
```
в результате на экране будет показан compose с уже подставленными значениями переданных переменных
[вверх](#top)
***
###### Chapter23
### Объединение конфигураций
Описание конфигурации можно разделить на несколько файлов, например для возможности запуска с разными параметрами
`docker-compose.yml`
```yaml
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
depends_on:
- db
volumes:
["./:/var/www/html"]
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: wp_db
MYSQL_USER: db_user
MYSQL_PASSWORD: wp_db_pass
MYSQL_ROOT_PASSWORD: db_root_pass
volumes:
- db:/var/lib/mysql
volumes:
db:
```
`docker-compose.wp.yml`
```yaml
version: '3.1'
services:
wordpress:
ports:
- 8080:80
environment:
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: db_user
WORDPRESS_DB_PASSWORD: wp_db_pass
```
Описание проброса портов и переменные перенесли в отдельный файл. Теперь запускать эти контейнеры можем используя как и раньше, но без проброса портов и передачи переменных в контейнер `docker-compose up -d`.
Так и объединив оба конфигурационных файла для полного запуска
```bash
docker-compose -f docker-compose.yml -f docker-compose.wp.yml up -d
```
Также можно добавить ссылку на другой конфиг в самом описании
`docker-compose.yml`
```yaml
version: '3.1'
services:
wordpress:
extends:
file: docker-compose.wp.yml
service: wordpress
depends_on:
- db
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: wp_db
MYSQL_USER: db_user
MYSQL_PASSWORD: wp_db_pass
MYSQL_ROOT_PASSWORD: db_root_pass
volumes:
- db:/var/lib/mysql
volumes:
db:
```
`docker-compose.wp.yml`
```yaml
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_NAME: wp_db
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: db_user
WORDPRESS_DB_PASSWORD: wp_db_pass
volumes:
["./:/var/www/html"]
```
В этом случае перечислять конфигурационные файлы при запуске не нужно.
[вверх](#top)
***
```bash
git add . && git commit -m 'mod docker' && git push
```