###### 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
```

