Docker compose volumes root

Техника

В данной инструкции мы приведем различные примеры по работе с docker-compose без подробного описания принципа работы. Данный материал можно использовать в качестве шпаргалки.

Проброс папок и томов в Docker решает следующие проблемы, позволяя монтировать директории хоста внутри контейнера либо создавая централизованное хранилище. Таким образом мы получаем следующие преимущества:

  1. Мы не копируем данные, они хранятся в одно месте для всех контейнеров
  2. Раньше копирование отнимало время, а сейчас это делать не нужно, контейнеры запускаются быстрее
  3. У нас появляется больше возможностей для управления данными
Содержание
  1. Что такое Docker Volumes
  2. Минуточку внимания
  3. Пересоздадим существующую структуру
  4. Версии
  5. Version 1
  6. Version 2
  7. Upgrading
  8. Networks
  9. Запуск docker-compose
  10. Healthcheck
  11. Читайте также
  12. Установка Docker Compose
  13. Файл docker-compose. yml
  14. Руководство по Docker Compose файлу
  15. Руководство по конфигурации сервисов
  16. build
  17. context
  18. dockerfile
  19. args
  20. cap_add, cap_drop
  21. command
  22. cgroup_parent
  23. container_name
  24. devices
  25. depends_on
  26. dns
  27. dns_search
  28. tmpfs
  29. entrypoint
  30. env_file
  31. environment
  32. expose
  33. extends
  34. external_links
  35. image
  36. labels
  37. links
  38. logging
  39. log_driver
  40. log_opt
  41. net
  42. network_mode
  43. networks
  44. aliases
  45. ipv4_address, ipv6_address
  46. pid
  47. ports
  48. security_opt
  49. stop_signal
  50. ulimits
  51. volumes, volume_driver
  52. volumes_from
  53. cpu_shares, cpu_quota, cpuset, domainname, hostname, ipc, mac_address, mem_limit, memswap_limit, privileged, read_only, restart, shm_size, stdin_open, tty, user, working_dir
  54. Инструкция VOLUME в Dockerfile
  55. Возможные ошибки
  56. Network <net-name>_default  Error
  57. Сервисы
  58. Variable substitution
  59. Порты контейнера
  60. Базовый шаблон
  61. Типы томов Docker
  62. Создание Volumes через docker run
  63. Папки и файлы
  64. Подключение volume
  65. Создание Volumes через Dockerfile
  66. Создание Volumes через docker-compose
  67. Использование внешних томов
  68. Создание тома в другой директории
  69. Монтирование через Tmpfs
  70. Просмотр привязанных томов
  71. Привязка томов из другого контейнера
  72. Создание и удаление Volume
  73. Network configuration reference
  74. driver
  75. driver_opts
  76. ipam
  77. external
  78. Volume configuration reference
  79. driver
  80. driver_opts
  81. external

Что такое Docker Volumes

Том — это файловая система, которая расположена на хост-машине за пределами контейнеров. Тома представляют собой средства для постоянного хранения информации и могут совместно использоваться разными контейнерами. Созданием и управлением томами занимается Docker.

Попробуем просто создать несколько томов:

 docker volume create --name data-www
 docker volume create --name data-sql
 docker volume create --name data-tmp

Для того, чтобы просмотреть список томов:

 docker volume ls
DRIVER              VOLUME NAME
local               data-sql
local               data-tmp
local               data-www

Посмотреть информацию об отдельном томе:

 docker volume inspect data-www
[
    {
        "CreatedAt": "2020-03-20T14:44:01+03:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/data-www/_data",
        "Name": "data-www",
        "Options": {},
        "Scope": "local"
    }
]

Если том больше не нужен, его можно удалить:

 docker volume rm data-tmp

Чтобы удалить все тома, которые не используются контейнерами:

 docker volume prune

Теперь смонтируем том data-www при запуске контейнера:

 docker run -it -v data-www:/var/www ubuntu:latest
 
 
 

Если вспомнить, что данные тома находятся в /var/lib/docker/volumes/data-www/_data, то теперь в этой директории есть поддиректория html, а внутри поддиректории — файл index.php.

Данная команда разворачивает все три сервиса используя конфигурацию из файлов docker-compose.yml и docker-compose.prod.yml (но не из конфигурации для разработки docker-compose.override.yml).

Есть несколько частей Compose, которые имеют дело с переменными окружения в том или ином смысле. Эта страница поможет вам найти нужную информацию.

В оболочке можно использовать переменные среды для заполнения значений внутри файла Compose:

Так же как и в docker run -e, вы можете задать переменные окружения в контейнере с помощью docker-compose run -e:

Вы так же можете передать переменную из shell если не будете задавать ее значение:

Вы можете установить значения по умолчанию для любых переменных среды, указанных в Compose файле или использовать для настройки Compose файл среды с именем .env:

Когда вы запускаете docker-compose up, сервис web определенный выше использует образ webapp:v1.5. Вы можете убедиться в этом с помощью команды настроек, которая выводит настройки вашего приложения в терминал:

Значения из оболочки имеют приоритет над переменными из .env файла. Если вы установите TAG в другое значение в вашей оболочке, будет произведена следующая подстановка:

$ export TAG=v2.0

$ docker-compose config
version: '2.0'
services:
  web:
    image: 'webapp:v2.0'

version: '3'
services:
    php:
        volumes:
            - "./web:/var/www/html"

Chown для ./web — root:root, пользователь www-data внутри контейнера не имеет прав на эту папку. Вероятно, нужно создать специального пользователя/группу с правами на эту папку и как-то передать его внутрь контейнера, но я не вижу в описании ключей для docker-compose.yml подходящего.


  • Вопрос задан

    более трёх лет назад

Это не вольюм это маунт и права на нем тежи, что и на ./web.
Поставь локально chmod 777 или монтируй /etc/passwd /etc/shadow и кастомайз контейнер, чтоб uid gid с хостом совпадали.

я в похожем случае в контейнер прокидывал /etc/passwd и /etc/groups
после этого связка имя-uid группа-gid работает.

Макс, не получается. После прописывания группы и пользователя сервер вообще перестает отвечать. С дописками по Вашей схеме (если, конечно, я ее верно понял) выходит вот так:

version: '3'
services:
    web:
        image: nginx:alpine
        volumes:
            - "./etc/nginx/default.conf:/etc/nginx/conf.d/default.conf"
            - "./etc/ssl:/etc/ssl"
            - "./web:/var/www/html"
            - "./etc/nginx/default.template.conf:/etc/nginx/conf.d/default.template"
            - "/etc/passwd:/etc/passwd"
            - "/etc/groups:/etc/groups"
        ports:
            - "80:80"
            - "3000:443"
        environment:
            - NGINX_HOST=${NGINX_HOST}
        command: /bin/sh -c "envsubst '$$NGINX_HOST' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
        restart: always
        user: "1001:1001"
        depends_on:
            - php
            - mysqldb
    php:
        build:
            context: .
            dockerfile: DockerfilePhpWithGit
        restart: always
        user: "1001:1001"
        volumes:
            - "./etc/php/php.ini:/usr/local/etc/php/conf.d/php.ini"
            - "./web:/var/www/html"
            - "/etc/passwd:/etc/passwd"
            - "/etc/groups:/etc/groups"

где 1001:1001 — пользователь www-data:www-data. Пользователь с таким же именем и группой создается в сервисе php

Я в такой ситуации в entrypoint.sh контейнера модифицировал локальных пользователей, получая uid из прав смонтированного каталога:

SRC_DIR=/path/to/mounted/volume
DIR=/path/to/dir
USER=www-data
GROU=www-data

$uid=$(stat -c '%u' $SRC_DIR)                                                                                                                    
$gid=$(stat -c '%g' $SRC_DIR)                                                                                                                    
echo $uid > /root/uid                                                                                                                          
echo $gid > /root/gid                                                                                                                          
usermod -u $uid $USER                                                                                                                                   
groupmod -g $gid $GROUP                                                                                                                                  
mkdir -p $DIR                                                                                                                                            
chown -R $USER:$GROUP $DIR

05 июл. 2023, в 15:59

1500 руб./за проект

05 июл. 2023, в 15:57

600 руб./в час

05 июл. 2023, в 15:53

1500 руб./в час

Минуточку внимания

В docker compose volumes — логические тома, которые задаются для каждого контейнера. Это директива в файле, определяющая связь точки монтирования на диске с другой точкой монтирования в контейнере.

Все, что находится в volumes сохраняется на диске после удаления контейнера. Остальные данные хранятся в памяти.

Основное предназначение Docker в быстром разворачивании окружения на любой машине из готовых образов, которые можно дорабатывать. Контейнер — временная структура, все изменения выполненные в нем существуют пока существует сам контейнер. На диске данные не сохраняются если они не вынесены в постоянную структуру — volume.

Для примера возьмем с dockerhub инструкцию для образа с wordpress, в немного измененном виде будем использовать ее.

Проект будет представлять собой сайт на wordpress с базой данных MySQL.

Сразу создадим каталоги под сайт и базу на хост машине. За счет биндинга они будут связаны с контейнерами

mkdir -p /home/site/db

На машине должны быть установлены сам Docker и docker-compose. Создаем docker-compose.yml

cd /home && mcedit docker-compose.yml

version: '2'

services:

  wordpress:
    image: wordpress
    restart: always
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: example
    links:
      - mysql:db
    volumes:
       - /home/site:/var/www/html
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
    volumes:
       - /home/site/db:/var/lib/mysql

В файле 2 сервиса. Структура типовая, 80 порт из контейнера пробрасывается на порт 8080 хост машины. Используются стандартные образы с dockerhub.

Для каждого контейнера заданы блоки volumes:

/home/site:/var/www/html для сайта

 /home/site/db:/var/lib/mysql для базы данных

Они определяют, что данные из временной структуры — контейнера будут сохраняться на хост машине.

Содержимое /var/www/html в /home/site, содержимое /var/lib/mysql в /home/site/db

Эта информация будет изменена при жизни контейнера и останется на хост машине после его удаления.

docker-compose -f docker-compose.yml up -d

Они успешно стартовали, с хоста обращаться к сервису можно только по порту 8080, на который пробрасываются запросы.

В браузере обратившись к IP адресу серверу и порту 8080 можно запустить установку CMS, затем попасть в административный раздел.

Внесем минимальные изменения в структуру перового поста. Поменяем заголовок ‘Hello World’ на ‘Hello Docker‘ и единственное существующее по-умолчанию предложение.

Docker compose volumes

Пересоздадим существующую структуру

И удаляем их

Контейнеров нет, с ключем -a  выводятся все контейнеры, в т.ч. незапущенные

docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

Файлы при этом сохранены на диске

Также как и содержимое /var/lib/mysql из контейнера

auto.cnf ca.pem client-key.pem ibdata1 ib_logfile1 performance_schema public_key.pem server-key.pem wordpress
ca-key.pem client-cert.pem ib_buffer_pool ib_logfile0 mysql private_key.pem server-cert.pem sys

При обращении к тому же URL:8080 сейчас будет возникать ошибка — веб-сервер, являющийся частью контейнера не работает.

Запускаем контейнеры через docker-compose вновь

docker-compose -f docker-compose.yml up -d

Creating home_mysql_1
Creating home_wordpress_1

Сейчас можно убедиться в том, что сайт вновь стал открываться и контент отображается в том же виде. При старте информация из docker-compose.yml  считалась.

Были задействованы те же каталоги, что использовались ранее, с имеющимися данными.

Читайте про управление контейнерами вручную. При использовании docker compose volumes задаются в файле, при ручном создании контейнера их можно указывать с ключем -v.

Версии

There are two versions of the Compose file format:

  • Version 1, the legacy format. This is specified by omitting a version key at the root of the YAML.
  • Version 2, the recommended format. This is specified with a version: ‘2’ entry at the root of the YAML.

To move your project from version 1 to 2, see the Upgrading section.

Several things differ depending on which version you use:

  • The structure and permitted configuration keys
  • The minimum Docker Engine version you must be running
  • Compose’s behaviour with regards to networking

These differences are explained below.

Version 1

Compose files that do not declare a version are considered “version 1”. In those files, all the services are declared at the root of the document.

Version 1 is supported by Compose up to 1.6.x. It will be deprecated in a future Compose release.

web:
  build: .
  ports:
   - "5000:5000"
  volumes:
   - .:/code
  links:
   - redis
redis:
  image: redis

Version 2

Compose files using the version 2 syntax must indicate the version number at the root of the document. All services must be declared under the services key.

Version 2 files are supported by Compose 1.6.0+ and require a Docker Engine of version 1.10.0+.

Named volumes can be declared under the volumes key, and networks can be declared under the networks key.

version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: redis

A more extended example, defining volumes and networks:

version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    networks:
      - front-tier
      - back-tier
  redis:
    image: redis
    volumes:
      - redis-data:/var/lib/redis
    networks:
      - back-tier
volumes:
  redis-data:
    driver: local
networks:
  front-tier:
    driver: bridge
  back-tier:
    driver: bridge

Upgrading

In the majority of cases, moving from version 1 to 2 is a very simple process:

  1. Indent the whole file by one level and put a services: key at the top.
  2. Add a version: ‘2’ line at the top of the file.

It’s more complicated if you’re using particular configuration features:

  • dockerfile: This now lives under the build key:

    build:
      context: .
      dockerfile: Dockerfile-alternate
  • log_driver, log_opt: These now live under the logging key:

    logging:
      driver: syslog
      options:
        syslog-address: "tcp://192.168.0.42:123"
  • links with environment variables: As documented in the environment variables reference, environment variables created by links have been deprecated for some time. In the new Docker network system, they have been removed. You should either connect directly to the appropriate hostname or set the relevant environment variable yourself, using the link hostname:

    web:
      links:
        - db
      environment:
        - DB_PORT=tcp://db:5432
  • external_links: Compose uses Docker networks when running version 2 projects, so links behave slightly differently. In particular, two containers must be connected to at least one network in common in order to communicate, even if explicitly linked together.

    Either connect the external container to your app’s default network, or connect both the external container and your service’s containers to an external network.

  • net: This is now replaced by network_mode:

    net: host    ->  network_mode: host
    net: bridge  ->  network_mode: bridge
    net: none    ->  network_mode: none
    net: "container:web"  ->  network_mode: "service:web"
    net: "container:cont-name"  ->  network_mode: "container:cont-name"
    net: "container:abc12345"   ->  network_mode: "container:abc12345"
  • volumes with named volumes: these must now be explicitly declared in a top-level volumes section of your Compose file. If a service mounts a named volume called data, you must declare a data volume in your top-level volumes section. The whole file might look like this:

    version: '2'
    services:
      db:
        image: postgres
        volumes:
          - data:/var/lib/postgresql/data
    volumes:
      data: {}

    By default, Compose creates a volume whose name is prefixed with your project name. If you want it to just be called data, declare it as external:

    volumes:
      data:
        external: true

Networks

Отдельно рассмотрим варианты сетевых настроек.

Список сетей, созданных для docker можно увидеть командой:

docker network ls

Получить подробную информацию по сети можно командой:

docker network inspect <имя сети>

1. Указать определенную подсеть. Задается с помощью опции subnet в отдельной секции networks. В последней мы создаем конфигурацию для определенной сети (в данном примере, default). Для конкретного сервиса мы также задаем привязку к созданной сети default в подразделе networks:

networks:
  default:
    ipam:
      driver: default
      config:
        — subnet: 172.28.0.0/16

* где 172.28.0.0/16 — подсеть, в которой будут работать все контейнеры, которые привязаны к созданной сети default.

2. Алиасы. Данная настройка позволит видеть контейнеры по альтернативным именам (по умолчанию, они обнаруживаются по имени контейнера). Настройка указывается в подразделе networks сервиса:

* в данном примере наш контейнер будет также резолвиться по имени <alternative_name>.

3. Внешняя сеть. Если необходимо, чтобы наши контейнеры могли видеть по сети другие контейнеры, создаем сеть external:

networks:
  dnet:
    external:
      name: dnet

networks:
  vpcbr:
    driver: bridge
    ipam:
     config:
       — subnet: 172.28.0.0/24
         gateway: 172.28.0.1

* в нашем примере будет создана подсеть 172.28.0.0/24, а контейнеру будет присвоен адрес 172.28.0.2.

* в данном примере имени foo будет соответствовать адрес 1.2.3.4, а bar — 5.6.7.8.

Запуск docker-compose

Рассмотрим различные примеры выполнения команды docker-compose.

1. Посмотреть версию:

2. Создание и запуск контейнеров:

docker-compose up -d

* напомним, что в текущем каталоге находится созданный файл с названием docker-compose.yml.

С указанием альтернатнативного файла docker-compose.

docker-compose -f /foo/bar/other-docker-compose.yml up -d

3. Перечитать файл docker-compose:

docker-compose up -d

* на самом деле, команда такая же, как для запуска. Система если определит, что есть изменения, пересоздаст контейнер.

Перечитать и пересобрать контейнеры, если есть инструкция build:

docker-compose up -d —build

4. Остановить контейнеры.

Только остановить контейнеры:

Остановить контейнеры с удаление данных (в volumes):

docker-compose down —volumes

Healthcheck

Данная директива, хоть и является частью сервиса, мы рассмотрим ее в отдельном разделе. Синтаксис:

  • test — наш скрипт, который должен вернуть 0, если все хорошо, или 1 — если все плохо.
  • interval — как часто запускать проверку.
  • timeout — как долго нужно ждать ответа.
  • retries — сколько раз тест должен вернуть отрицательный результат, чтобы контейнер перешел в состояние «unhealthy».

1. Проверка работы веб-портала. Рассмотрим пример, когда сайт при правильной работы должен возвращать слово works:

* в данном примере мы запросим у нашего сервера страницу по http и выведем строку, в которой есть слово works. Если такой строки не найдется, команда вернет код 1.

2. Проверка СУБД mysql. Проверку можно выполнить с помощью запроса SELECT 1. В композ-файле это выглядит так:

Читайте также

Другие инструкции, связанные с Docker:

1. Установка Docker на Linux.

2. Создание собственного образа Docker.

3. Настройка локального репозитория для образов Docker и работа с ним.

Установка Docker Compose

Docker применяется для управления отдельными контейнерами (сервисами), из которых состоит приложение. Docker Compose используется для одновременного управления несколькими контейнерами, входящими в состав приложения. Этот инструмент предлагает те же возможности, что и Docker, но позволяет работать с более сложными приложениями.

 sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" \
 
 sudo chmod +x /usr/local/bin/docker-compose
 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
 
docker-compose version 1.25.4, build 8d51620a

Файл docker-compose. yml

Набор сервисов, которые нужны для работы приложения, определяется с помощью файла docker-compose.yml. У нас уже есть директория www — создадим в ней еще один файл:

 
 

  
    
       .
    
       8080:80

Теперь построчно разберёмся с параметрами:

  • version — какая версия docker-compose.yml используется
  • services — контейнеры, которые нужно запустить
  • app — имя сервиса, может быть любым, но осмысленным
  • build — шаги, описывающие процесс билдинга
  • context — где находится Dockerfile для контейнера
  • ports — соответствие портов хоста и контейнера

Теперь проект надо собрать — это похоже на сборку образа в Docker, но здесь идет сборка нескольких образов. Хотя в нашем случае образ всего один:

 

Проверим, что был создан новый образ:

 
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
--------------------------------------------------------------------------------------------
www_app                   latest              ce3c26a2cb52        17 seconds ago      410MB
apache-php72              latest              eb9a7fb87880        22 hours ago        410MB
ubuntu-share-etc          latest              ebc1eef0eca3        42 hours ago        64.2MB
php                       7.2-apache          4e96f7d06518        2 days ago          410MB
php-cli-script            latest              9fff2bf618ad        2 days ago          398MB
tokmakov/apache2_ubuntu   latest              18073a80c28b        3 days ago          191MB
php                       7.2-cli             555ec78042a1        3 weeks ago         398MB
ubuntu                    latest              72300a873c2c        4 weeks ago         64.2MB
hello-world               latest              fce289e99eb9        14 months ago       1.84kB

Теперь запустим эти сервисы, которые создали (хотя у нас всего один сервис):

 
Creating network "www_default" with the default driver
Creating www_app_1 ... done
Attaching to www_app_1
app_1  | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message
app_1  | AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message
app_1  | [Sun Mar 22 08:31:46.482140 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.2.29 configured -- resuming normal operations
app_1  | [Sun Mar 22 08:31:46.486761 2020] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

Запускаем браузер и открываем http://localhost:8080:

Остановим работу контейнера с помощью Ctrl+C и посмотрим на список контейнеров:

 docker container ls -a
CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS                      PORTS   NAMES
--------------------------------------------------------------------------------------------------------------------------------

a6e37dee6924   apache-php72     "docker-php-entrypoi…"   2 hours ago      Exited (0) 2  hours ago             beautiful_turing
................................................................................................................................
8aa1a9458932   php-cli-script   "php /script.php 8"      2 days ago       Exited (0) 2 days ago               optimistic_maxwell
37def446ae84   ubuntu           "/bin/bash"              4 days ago       Exited (0) 2 days ago               apache2_ubuntu

Поиск:
CLI • Docker • Linux • Ubuntu • Виртуализация • Команда • Настройка • Процесс • Установка

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Руководство по Docker Compose файлу

Compose файл использует YAML формат и определяет сервисысети и тома. По умолчанию Compose файл имеет имя ./docker-compose.yml и располагается в корне проекта.

Определение сервиса contains configuration which will be applied to each container started for that service, much like passing command-line parameters to docker run. Также, network and volume definitions are analogous to docker network create and docker volume create.

As with docker run, options specified in the Dockerfile (e.g., CMD, EXPOSE, VOLUME, ENV) are respected by default — you don’t need to specify them again in docker-compose.yml.

Руководство по конфигурации сервисов

В этом разделе содержится список всех параметров конфигурации, поддерживаемых определением службы.

build

Параметры конфигурации, которые применяются во время сборки.

build можно указать либо как строку, содержащую путь к контексту сборки, либо как объект с путем, указанным в контексте и, возможно, dockerfile и args.

build: ./dir  
build:
  context: ./dir
  dockerfile: Dockerfile-alternate
  args:
    buildno: 1

If you specify image as well as build, then Compose names the built image with the webapp and optional tag specified in image:

build: ./dir
image: webapp:tag

This will result in an image named webapp and tagged tag, built from ./dir.

Note: In the version 1 file format, build is different in two ways:

  • Only the string form (build: .) is allowed — not the object form.
  • Using build together with image is not allowed. Attempting to do so results in an error.

context

Either a path to a directory containing a Dockerfile, or a url to a git repository.

When the value supplied is a relative path, it is interpreted as relative to the location of the Compose file. This directory is also the build context that is sent to the Docker daemon.

Compose will build and tag it with a generated name, and use that image thereafter.

dockerfile

Compose will use an alternate file to build with. A build path must also be specified.

build:
  context: .
  dockerfile: Dockerfile-alternate
  • It appears alongside build, not as a sub-option:

    build: .
    dockerfile: Dockerfile-alternate
  • Using dockerfile together with image is not allowed. Attempting to do so results in an error.

args

Add build arguments, which are environment variables accessible only during the build process.

First, specify the arguments in your Dockerfile:

ARG buildno
ARG password

RUN echo "Build number: $buildno"
RUN script-requiring-password.sh "$password"

Then specify the arguments under the build key. You can pass either a mapping or a list:

build:
  context: .
  args:
    buildno: 1
    password: secret

build:
  context: .
  args:
    - buildno=1
    - password=secret

You can omit the value when specifying a build argument, in which case its value at build time is the value in the environment where Compose is running.

args:
  - buildno
  - password

Note: YAML boolean values (true, false, yes, no, on, off) must be enclosed in quotes, so that the parser interprets them as strings.

cap_add, cap_drop

Add or drop container capabilities. See man 7 capabilities for a full list.

cap_add:
  - ALL

cap_drop:
  - NET_ADMIN
  - SYS_ADMIN

command

Override the default command.

command: bundle exec thin -p 3000

The command can also be a list, in a manner similar to dockerfile:

command: [bundle, exec, thin, -p, 3000]

cgroup_parent

Specify an optional parent cgroup for the container.

cgroup_parent: m-executor-abcd

container_name

Specify a custom container name, rather than a generated default name.

container_name: my-web-container

Because Docker container names must be unique, you cannot scale a service beyond 1 container if you have specified a custom name. Attempting to do so results in an error.

devices

List of device mappings. Uses the same format as the —device docker client create option.

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

depends_on

Express dependency between services, which has two effects:

version: '2'
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

dns

Custom DNS servers. Can be a single value or a list.

dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9

Custom DNS search domains. Can be a single value or a list.

dns_search: example.com
dns_search:
  - dc1.example.com
  - dc2.example.com

tmpfs

Mount a temporary file system inside the container. Can be a single value or a list.

tmpfs: /run
tmpfs:
  - /run
  - /tmp

entrypoint

Override the default entrypoint.

entrypoint: /code/entrypoint.sh

The entrypoint can also be a list, in a manner similar to dockerfile:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

env_file

Add environment variables from a file. Can be a single value or a list.

If you have specified a Compose file with docker-compose -f FILE, paths in env_file are relative to the directory that file is in.

Environment variables specified in environment override these values.

env_file: .env  
env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env
# Set Rails/Rack environment
RACK_ENV=development

Note: If your service specifies a build option, variables defined in environment files will not be automatically visible during the build. Use the args sub-option of build to define build-time environment variables.

environment

Add environment variables. You can use either an array or a dictionary. Any boolean values; true, false, yes no, need to be enclosed in quotes to ensure they are not converted to True or False by the YML parser.

Environment variables with only a key are resolved to their values on the machine Compose is running on, which can be helpful for secret or host-specific values.

environment:
  RACK_ENV: development
  SHOW: 'true'
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SHOW=true
  - SESSION_SECRET

Note: If your service specifies a build option, variables defined in environment will not be automatically visible during the build. Use the args sub-option of build to define build-time environment variables.

expose

Expose ports without publishing them to the host machine — they’ll only be accessible to linked services. Only the internal port can be specified.

expose:
 - "3000"
 - "8000"

extends

Extend another service, in the current file or another, optionally overriding configuration.

You can use extends on any service together with other configuration keys. The extends value must be a dictionary defined with a required service and an optional file key.

extends:
  file: common.yml
  service: webapp

The service the name of the service being extended, for example web or database. The file is the location of a Compose configuration file defining that service.

If you omit the file Compose looks for the service configuration in the current file. The file value can be an absolute or relative path. If you specify a relative path, Compose treats it as relative to the location of the current file.

You can extend a service that itself extends another. You can extend indefinitely. Compose does not support circular references and docker-compose returns an error if it encounters one.

external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql

Note: If you’re using the version 2 file format, the externally-created containers must be connected to at least one of the same networks as the service which is linking to them.

Add hostname mappings. Use the same values as the docker client —add-host parameter.

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

An entry with the ip address and hostname will be created in /etc/hosts inside containers for this service, e.g:

162.242.195.82  somehost
50.31.209.229   otherhost

image

Specify the image to start the container from. Can either be a repository/tag or a partial image ID.

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd

If the image does not exist, Compose attempts to pull it, unless you have also specified build, in which case it builds it using the specified options and tags it with the specified tag.

Note: In the version 1 file format, using build together with image is not allowed. Attempting to do so results in an error.

labels

Add metadata to containers using Docker labels. You can use either an array or a dictionary.

It’s recommended that you use reverse-DNS notation to prevent your labels from conflicting with those used by other software.

labels:
  com.example.description: "Accounting webapp"
  com.example.department: "Finance"
  com.example.label-with-empty-value: ""

labels:
  - "com.example.description=Accounting webapp"
  - "com.example.department=Finance"
  - "com.example.label-with-empty-value"

Link to containers in another service. Either specify both the service name and a link alias (SERVICE:ALIAS), or just the service name.

web:
  links:
   - db
   - db:database
   - redis

Containers for the linked service will be reachable at a hostname identical to the alias, or the service name if no alias was specified.

Links also express dependency between services in the same way as depends_on, so they determine the order of service startup.

logging

Logging configuration for the service.

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

The driver name specifies a logging driver for the service’s containers, as with the —log-driver option for docker run (documented here).

The default value is json-file.

driver: "json-file"
driver: "syslog"
driver: "none"

Note: Only the json-file driver makes the logs available directly from docker-compose up and docker-compose logs. Using any other driver will not print any logs.

Specify logging options for the logging driver with the options key, as with the —log-opt option for docker run.

Logging options are key-value pairs. An example of syslog options:

driver: "syslog"
options:
  syslog-address: "tcp://192.168.0.42:123"

log_driver

Specify a log driver. The default is json-file.

log_opt

Specify logging options as key-value pairs. An example of syslog options:

log_opt:
  syslog-address: "tcp://192.168.0.42:123"

net

net: "bridge"
net: "host"
net: "none"
net: "container:[service name or container name/id]"

network_mode

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

services:
  some-service:
    networks:
     - some-network
     - other-network

aliases

Aliases (alternative hostnames) for this service on the network. Other containers on the same network can use either the service name or this alias to connect to one of the service’s containers.

Since aliases is network-scoped, the same service can have different aliases on different networks.

The general format is shown here.

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
         - alias3
      other-network:
        aliases:
         - alias2

In the example below, three services are provided (web, worker, and db), along with two networks (new and legacy). The db service is reachable at the hostname db or database on the new network, and at db or mysql on the legacy network.

version: '2'

services:
  web:
    build: ./web
    networks:
      - new

  worker:
    build: ./worker
    networks:
    - legacy

  db:
    image: mysql
    networks:
      new:
        aliases:
          - database
      legacy:
        aliases:
          - mysql

networks:
  new:
  legacy:

ipv4_address, ipv6_address

Specify a static IP address for containers for this service when joining the network.

version: '2'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      driver: default
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.16.238.1
      - subnet: 2001:3984:3989::/64
        gateway: 2001:3984:3989::1

pid

Sets the PID mode to the host PID mode. This turns on sharing between container and the host operating system the PID address space. Containers launched with this flag will be able to access and manipulate other containers in the bare-metal machine’s namespace and vise-versa.

ports

Expose ports. Either specify both ports (HOST:CONTAINER), or just the container port (a random host port will be chosen).

Note: When mapping ports in the HOST:CONTAINER format, you may experience erroneous results when using a container port lower than 60, because YAML will parse numbers in the format xx:yy as sexagesimal (base 60). For this reason, we recommend always explicitly specifying your port mappings as strings.

ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"

security_opt

Override the default labeling scheme for each container.

security_opt:
  - label:user:USER
  - label:role:ROLE

stop_signal

Sets an alternative signal to stop the container. By default stop uses SIGTERM. Setting an alternative signal using stop_signal will cause stop to send that signal instead.

ulimits

Override the default ulimits for a container. You can either specify a single limit as an integer or soft/hard limits as a mapping.

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes, volume_driver

Mount paths or named volumes, optionally specifying a path on the host machine (HOST:CONTAINER), or an access mode (HOST:CONTAINER:ro). For version 2 files, named volumes need to be specified with the top-level volumes key. When using version 1, the Docker Engine will create the named volume automatically if it doesn’t exist.

volumes:
  # Just specify a path and let the Engine create a volume
  - /var/lib/mysql

  # Specify an absolute path mapping
  - /opt/data:/var/lib/mysql

  # Path on the host, relative to the Compose file
  - ./cache:/tmp/cache

  # User-relative path
  - ~/configs:/etc/configs/:ro

  # Named volume
  - datavolume:/var/lib/mysql

If you do not use a host path, you may specify a volume_driver.

Note that for version 2 files, this driver will not apply to named volumes (you should use the driver option when declaring the volume instead). For version 1, both named volumes and container volumes will use the specified driver.

Note: No path expansion will be done if you have also specified a volume_driver.

volumes_from

Mount all of the volumes from another service or container, optionally specifying read-only access (ro) or read-write (rw). If no access level is specified, then read-write will be used.

volumes_from:
 - service_name
 - service_name:ro
 - container:container_name
 - container:container_name:rw
- service_name
- service_name:ro
- container_name
- container_name:rw

cpu_shares, cpu_quota, cpuset, domainname, hostname, ipc, mac_address, mem_limit, memswap_limit, privileged, read_only, restart, shm_size, stdin_open, tty, user, working_dir

Each of these is a single value, analogous to its docker run counterpart.

cpu_shares: 73
cpu_quota: 50000
cpuset: 0,1

user: postgresql
working_dir: /code

domainname: foo.com
hostname: foo
ipc: host
mac_address: 02:42:ac:11:65:43

mem_limit: 1000000000
memswap_limit: 2000000000
privileged: true

restart: always

read_only: true
shm_size: 64M
stdin_open: true
tty: true

Инструкция VOLUME в Dockerfile

Эта инструкция устарела и использовать ее не рекомендуется. Но давайте все таки познакомимся с ней поближе для общего понимания. Создадим в домашней директории каталог test и внутри него — файл Dockerfile:

 
 
 
 
FROM ubuntu:latest
VOLUME /etc

Соберем образ из этого Dockerfile:

 

Запустим новый контейнер:

 

Теперь посмотрим, какие тома существуют:

 docker volume ls
DRIVER              VOLUME NAME
local               8bda345c875c99d61f9646a9b0922934a7eaab83366c04159f6023654237f090
local               data-sql
local               data-www

Где физически расположены тома, мы уже знаем. Так что посмотрим содержимое нового тома:

 
 sudo ls /var/lib/docker/volumes/8bda345c875c99d61f9646a9b0922934a7eaab83366c04159f6023654237f090/_data/
adduser.conf            debconf.conf    fstab         hosts        ld.so.conf     lsb-release    opt         profile.d  rc5.d        security  subuid
alternatives            debian_version  gai.conf      init.d       ld.so.conf.d   machine-id     os-release  rc0.d      rc6.d        selinux   sysctl.conf
apt                     default         group         issue        legal          mke2fs.conf    pam.conf    rc1.d      rcS.d        shadow    sysctl.d
bash.bashrc             deluser.conf    gshadow       issue.net    libaudit.conf  mtab           pam.d       rc2.d      resolv.conf  shells    systemd
bindresvport.blacklist  dpkg            host.conf     kernel       login.defs     networks       passwd      rc3.d      rmt          skel      terminfo
cron.daily              environment     hostname      ld.so.cache  logrotate.d    nsswitch.conf  profile     rc4.d      securetty    subgid    update-motd.d

Это содержимое каталога /etc контейнера. Так что мы можем, используя инструкцию VOLUME, сохранять на основной системе любые директории контейнера. И при удалении контейнера тома будут по-прежнему существовать. Впрочем, можно вместе с удалением контейнера удалить и связанный с ним том:

 

Возможные ошибки

Network <net-name>_default  Error

При попытке запустить compose получаем ошибку:

 Network <net-name>_default  Error
failed to create network <net-name>_default: Error response from daemon: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

Решение: быстрее всего выполнить чистку docker от неиспользуемых сетей. Для этого выполняем команду:

docker network prune

Сервисы

В данном разделе рассмотрим примеры настроек сервисов (контейнеров). Синтаксис:

services:
  <имя сервиса>:
    <настройки сервиса>

1. Создание контейнера из готового образа. Образ указывается с помощью директивы image:

* в данном примере будет взят образ nginx для поднятия контейнера.

2. Сборка контейнера из Dockerfile. Для этого используем опцию build:

    build:
      context: ./web-server/
      args:
        buildno: 22042001

  • build — указание на необходимость сборки из Dockerfile. Пример создания последнего читайте в инструкции Создание собственного образа Docker.
  • context — путь, где нужно искать Dockerfile относительно места, где находится docker-compose файл.
  • buildno — номер для сборки.

3. Проброс папок (volumes). Настраивается с помощью опции volumes:

    volumes:
      — /data/mysql:/var/lib/mysql

* в нашем примере мы смонтируем локальный каталог /data/mysql на хосте внутрь контейнера в качестве каталога /var/lib/mysql.

Также мы можем смонтировать папку только на чтение, например:

    volumes:
      — /:/rootfs:ro

4. Работа с портами. Рассмотрим несколько вариантов работы с портами.

а) Ports (внешняя публикация). С помощью данной опции мы можем указывать, на каких портах должен слушать контейнер и на какие порты должны пробрасываться запросы:

    ports:
      — 8080:80

* в данном примере наш контейнер будет слушать запросы на порту 8080 и передавать их внутрь контейнера на порт 80.

Или можно прописать так:

    ports:
      — 80

* в этом примере будет настроен проброс на порт 80. Внешний порт будет выбран docker автоматически.

б) Expose (внутрення публикация). Данная опция задает порт, на котором должно слушать приложение внутри контейнера, но проброса с внешнего адреса не будет — отправить запрос по сети на данный порт можно с другого контейнера:

    expose:
      — 7000

5. Переменные окружения. В нашей универсальной заготовке мы уже использовали одну системную переменную:

    environment:
      TZ: «Europe/Moscow»

Чтобы передать несколько переменных, просто их перечисляем:

    environment:
      TZ: «Europe/Moscow»
      MYSQL_ROOT_PASSWORD=password

Для каждого приложения есть свой набор системных переменных, которые оно понимает и интерпретирует. Например, MYSQL_ROOT_PASSWORD поймет СУБД и установит значение в качестве пароля для пользователя root.

Также системные переменные можно передать не в сценарии docker-compose, а в файле .env — просто создадим этот файл в одной директории с файлом docker-compose.yml:

6. Зависимости для контейнеров. Мы можем указать с помощью опции depends_on, от какого контейнера зависит сервис:

    depends_on:
      — db

* в конкретном примере, контейнер не запустится, пока не поднимется db.

7. Переопределить команду. С помощью директивы command мы можем переопределить команду для запуска, например:

* в данном примере мы запустим redis-server с альтернативным конфигурационным файлом.

Или можно написать так:

    command:
      — redis-server
      — /usr/local/etc/redis/redis.conf

Но если нам понадобиться запустить несколько последовательных команд, рабочий вариант с использованием bash:

    command: bash -c «yarn install && yarn start»

или если в контейнере нет bash:

    command: sh -c «yarn install && yarn start»

8. Метки. С помощью опции labels мы можем указывать дополнительную информацию для ориентирования или фильтров при поиске контейнеров:

* данные могут быть произвольные. Обратите внимание, что в качестве значений мы указали переменные, которые можно просто передать из системного окружения.

10. Домашняя директория. Определяет положение по умолчанию, откуда будут выполняться команды.

Variable substitution

Your configuration options can contain environment variables. Compose uses the variable values from the shell environment in which docker-compose is run. For example, suppose the shell contains EXTERNAL_PORT=8000 and you supply this configuration:

web:
  build: .
  ports:
    - "${EXTERNAL_PORT}:5000"

When you run docker-compose up with this configuration, Compose looks for the EXTERNAL_PORT environment variable in the shell and substitutes its value in. In this example, Compose resolves the port mapping to «8000:5000» before creating the web container.

If an environment variable is not set, Compose substitutes with an empty string. In the example above, if EXTERNAL_PORT is not set, the value for the port mapping is :5000 (which is of course an invalid port mapping, and will result in an error when attempting to create the container).

You can use a $$ (double-dollar sign) when your configuration needs a literal dollar sign. This also prevents Compose from interpolating a value, so a $$ allows you to refer to environment variables that you don’t want processed by Compose.

web:
  build: .
  command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"

If you forget and use a single dollar sign ($), Compose interprets the value as an environment variable and will warn you:

The VAR_NOT_INTERPOLATED_BY_COMPOSE is not set. Substituting an empty string.

Порты контейнера

Docker позволяет получить доступ к какому-то из портов контейнера, пробросив его наружу — в основную операционную систему. По умолчанию, мы не можем достучаться к какому-либо порту контейнера. Однако, интсрукция EXPOSE в Dockerfile позволяет объявить, к какому из портов можно обратиться из основной системы.

Создадим в домашней директории каталог www и внутри него — файлы Dockerfile и index.php:

 
 
 
 
# Образ с DockerHub, включает Apache и PHP
FROM php:7.2-apache
# Копируем все файлы проекта в контейнер
COPY . /var/www/html
# Сообщаем, какие порты контейнера слушать
EXPOSE 80
 
Hello from Apache
  

Создадим новый образ из Dockerfile:

 docker build . --tag apache-php72

Запустим контейнер и укажем, что порт 80 контейнера будет связан с портом 8080 хоста:

 docker run -p 8080:80 apache-php72
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat Mar 21 10:19:35.224973 2020] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.38 (Debian) PHP/7.2.29 configured -- resuming normal operations
[Sat Mar 21 10:19:35.233317 2020] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

Запускаем браузер и открываем http://localhost:8080:

Базовый шаблон

В первую очередь, предлагаю заготовку для docker-compose файла, на основе которой можно начинать писать свой сценарий для docker.

Создаем файл для работы с контейнерами:

  <srv_name>:
    image: <image_name>
    container_name: <container_name>
    hostname: <hostname>
    restart: unless-stopped
    environment:
      TZ: «Europe/Moscow»
    networks:
      — default

networks:
  default:
    ipam:
      driver: default
      config:
        — subnet: 172.28.0.0/16

  • services — основной раздел, где мы будем создавать и описывать наши сервисы (контейнеры docker). В данном примере сервис один. Для добавления еще одного добавляем еще строчки <srv_name>.
    • <srv_name> — название для нашего сервиса, на основе которого будет создан контейнер.
    • image — имя образа, который будет использоваться для создания контейнера.
    • container_name — имя, которое получен созданный контейнер.
    • hostname — имя хоста внутри контейнера.
    • restart — поведения контейнера при падении. В нашем примере мы указываем на необходимость автоматической перезагрузки, за исключением случаев, когда мы его сами остановили командой stop.
    • environment — задаем переменные окружения. В нашем примере только одна, которая указывает на часовой пояс (московское время).
    • networks — привязываем наш контейнер к сети. Опционально, но лучше определять самому подсеть. Это упрощает настройку некоторых сервисов, например, мы можем ограничить доступ для определенных подсетей и не желательно, чтобы подсети задавалась случайным образом.
  • networks — описание для сети. В нашем примере используются стандартные настройки, но указывается конкретная подсеть 172.28.0.0/16.

Типы томов Docker

Есть два основных способа обмена данными с контейнером, которые часто называют томами:

  • Перенаправление папки или файла с хоста в контейнер, называется bind mount
  • Создание специального объекта, который имеет больше возможностей управления данными volume
  • В случае bind mount файл index.html, внутри контейнера, будет удален. Это произойдет даже если папка хоста пустая
  • В случае volume при первом использовании файл index.html будет скопирован. При последующих удален

Создание Volumes через docker run

Для монтирования данных используются следующие параметры:

  • -v или --volume
  • --mount

Их различие в том, что bind mount более явно заставляет указывать источник и цель монтирования папки. Вы можете использовать эти параметры совместно, отдельно, повторяя несколько раз, ограничений нет.

Папки и файлы

Для примера, у меня есть следующая папка на хосте:

/home/alex/docker_data

В случае параметра -v указывается два пути откуда:куда. В случае --mount это именованные параметры разделенные запятыми, пример работы обоих:

-v /home/alex/docker_data:/usr/share/nginx/html

--mount type=bind,source=/home/alex/docker_data,destination=/usr/share/nginx/html

В mount мы используем следующие параметры:

  • type со значением bind говорит, что мы монтируем папку или файл
  • source источник, папка или файл, который мы хотим подключить к контейнеру
  • destination папка или файл внутри контейнера

В обоих случаях мы можем монтировать данный доступные только для чтения read-only добавив ro в конце:

-v /home/alex/docker_data:/usr/share/nginx/html:ro

--mount type=bind,source=/home/alex/docker_data,destination=/usr/share/nginx/html,ro

Так выглядит запуск контейнера с проброшенной папкой:

docker run -d --name nginx_vol1 -v /home/alex/docker_data:/usr/share/nginx/html:ro nginx

docker run -d --name nginx_vol2 --mount type=bind,source=/home/alex/docker_data,destination=/usr/share/nginx/html,ro nginx

Можно задать следующие опции:

  1. rprivate
  2. private
  3. rshared
  4. shared
  5. rslave
  6. slave
  7. ro режим только для чтения
  8. z папка на хосте может быть использована несколькими контейнерами
  9. Z папка используется только одним контейнером

Первые шесть параметров позволяют управлять тем, как будут влиять изменения в одной точке монтирования тома на другие точки монтирования. По умолчанию используется rprivate, что означает — никак.

Подключение volume

При монтировании тома нужно учитывать следующие моменты:

  • Название тома указывается без слешей
  • Если тома с этим названием нет, он будет создан
  • В случае с mount, в параметре type, указывается volume

При использовании docker run использование томов будет выглядеть так:

docker run -d --name nginx_vol1 -v docker_volume:/usr/share/nginx/html nginx

docker run -d --name nginx_vol2 --mount type=volume,source=docker_volume,destination=/usr/share/nginx/html nginx

Так же как и с папками мы можем добавить :ro или ,ro в конец значения, что бы дать права только на чтение директорий.

В предыдущем примере один том был подключен к двум контейнерам. Их совместную работу можно проверить создав файл в одном контейнере, а вывести через другой:

# создаем файл в одном контейнере
docker exec nginx_vol1 touch /usr/share/nginx/html/file1
# проверяем файл через другой контейнер
docker exec nginx_vol2 ls /usr/share/nginx/html

Создание Volumes через Dockerfile

При создании образа через Dockerfile у вас есть возможность создать том, но не использовать существующий. Смонтировать папку, через Dockerfile, нельзя.

Создание тома будет иметь ряд ограничений:

  1. Вы не сможете указать имя тома или выбрать существующий. Имя будет сгенерировано автоматически
  2. В любом случае том будет создан во время запуска контейнера т.е. так же как и в случае использования -v
  3. Каждое создание контейнера будет создавать новый том

Для создания тома есть инструкция VOLUME, пример синтаксиса:

FROM nginx
# указываем точку монтирования внутри контейнера
VOLUME /somedata1

Примерный результат где запускаются 2 контейнера с одного образа:

Volumes в Docker 1

Аналогичный результат можно получить используя одну из следующих команд:

docker run -v /somedata1 nginx

docker run -v  $(docker volume create):/somedata1 nginx

Volumes в Docker 2

Если вы используете инструкцию VOLUME и параметр -v указывающий на одну и ту же директорию, то -v возьмет верх.

Создание Volumes через docker-compose

Docker-compose позволяет запускать несколько контейнеров используя один файл инструкций. Синтаксис монтирования томов может быть ограниченным и расширенным так же как -v и --mount.

Для монтирования тома, кроме инструкции в самом контейнере, нужно указать дополнительную инструкцию volumes в верхнем уровне. Для папки этого делать не нужно:

version: "3.8"
services:
  web:
    image: nginx:alpine
    volumes:
      # том
      - somevol:/app
      # папка
      - /home/alex:/app2
# для тома
volumes:
  somevol:

Том somevol может использоваться совместно в нескольких контейнерах.

Если нам нужно дать права на том или папку, то мы просто добавляем ro или rw в конец пути:

...
    volumes:
      # том
      - somevol:/app:ro
      # папка
      - /home/alex:/app2:rw
...

Для монтирования так же есть расширенный синтаксис, похожий на команду mount в docker. Следующий пример аналогичен предыдущем по эффекту:

version: "3.8"
services:
  web:
    image: nginx:alpine
    volumes:
      # том
      - type: volume
        source: somevol
        target: /app1
      # папка
      - type: bind
        source: /home/alex
        target: /app2
volumes:
  somevol:

Есть еще инструкции, которые вы можете использовать. Ниже только их часть, но они используются редко:

volumes:
      - type: volume
        source: somevol
        target: /app1
        # папка только для чтения
        read_only: true
        # не будет копировать файлы в том, которые уже находятся в контейнере
        volume:
           nocopy: true
      # папка
      - type: bind
        source: /home/alex
        target: /app2
        # папка только для чтения
        read_only: true
        # создаст папку на хосте если ее нет
        create_host_path: true

Мы можем использовать один и тот же том в нескольких контейнерах (сервисах). Кроме этого есть инструкция volumes_from, которая использует тома с указанного контейнера, ниже оба примера:

version: "3.8"
services:
  container1:
    image: nginx:alpine
    volumes:
      - somevol:/app1
      - /home/alex:/app2
  container2:
    image: nginx:alpine
    volumes:
      # тот же том, но в другом контейнере
      - somevol:/app2
  container3:
    image: nginx:alpine
    # берем тома из сервиса container1
    # с доступностью только на чтение
    volumes_from:
      - container1:ro
volumes:
  somevol:

Использование внешних томов

Если вам нужно использовать том, который был создан не в текущем файле docker-compose.yml, то вы можете его указать через параметр external, автоматический такой том не создается:

...
volumes:
  somevol:
    external: true

Создание тома в другой директории

Через docker-compose.yml мы можем указывать драйвера и опции. Например, создадим тома в другой директории по аналогии с тем, что делали выше:

...
volumes:
  my_test_volume:
    driver: local
    driver_opts:
       o: bind
       type: none
       device: /home/alex/compose_vol1

Монтирование через Tmpfs

Еще одним способом монтирования томов является tmpfs. Данные этого тома хранятся в оперативной памяти. При остановке контейнера, в отличие от других томов, данные будут удалены. Эти данные просто не выгружаются из оперативной памяти. Такой тип тома вы можете создать только на одном контейнере и только в Linux.

Такие типы хранилищ редко используются. Их можно использовать для хранения чувствительных данных (для безопасности) или что бы ускорить работу какого-то приложения, но оба варианта, обычно, реализовываются на стороне приложения. Есть два способа создания tmpfs.

docker run \
  --tmpfs /app \
  nginx:latest
# или
docker run -d \
  --mount type=tmpfs,destination=/app,tmpfs-size=400,tmpfs-mode=1777 \
  nginx:latest

При использовании параметра --tmpfs вы можете указать только директорию, которую планируете использовать.

При использовании mount у вас появляются не обязательные параметры:

  • tmpfs-size размер в байтах, по умолчанию не ограничен
  • tmpfs-mode права на файлы, по умолчанию 1777. Можно не указывать специальные разрешения (т.е. 700, например).

Второй способ через docker-compose.yml:

volumes:
  foo:
    driver: local
    driver_opts:
      type: "tmpfs"
      o: "o=size=100m,uid=1000"
      device: "tmpfs"

Просмотр привязанных томов

Вы можете объявлять тома внутри смонтированных папок и наоборот. Это может создавать путаницу, но это требуется в определенных ситуациях. Например некоторые фреймворки используют следующую структуру хранение модулей и приложений:

docker inspect название_контейнера --format "'{{json .Mounts}}'"
sudo docker inspect название_контейнера | grep Mountpoint | awk '{ print $2 }'

Привязка томов из другого контейнера

С помощью параметра --volumes-from мы можем скопировать тома у запущенного или остановившегося тома, в значении мы указываем контейнер:

# контейнер 1
docker run -v $(pwd)/app:/usr/src/app \
           -v node_modules:/usr/src/app/node_modules \
           --name node1 \
           node
# контейнер 2
docker run --volumes-from node1 --name node2 node

Создание и удаление Volume

volume это отдельны объект у docker есть команды, с помощью которых можно им управлять:

Выведет список томов:

docker volume ls

Покажет подробную информацию о томе, даже его расположение на хосте:

docker volume inspect

Создание нового тома:

docker volume create

Удалит все тома, которые не используются контейнерами:

docker volume prune

Удалит один том:

docker volume rm

Network configuration reference

The top-level networks key lets you specify networks to be created. For a full explanation of Compose’s use of Docker networking features, see the Networking guide.

driver

Specify which driver should be used for this network.

The default driver depends on how the Docker Engine you’re using is configured, but in most instances it will be bridge on a single host and overlay on a Swarm.

The Docker Engine will return an error if the driver is not available.

driver_opts

  driver_opts:
    foo: "bar"
    baz: 1

ipam

Specify custom IPAM config. This is an object with several properties, each of which is optional:

  • driver: Custom IPAM driver, instead of the default.
  • config: A list with zero or more config blocks, each containing any of the following keys:
    • subnet: Subnet in CIDR format that represents a network segment
    • ip_range: Range of IPs from which to allocate container IPs
    • gateway: IPv4 or IPv6 gateway for the master subnet
    • aux_addresses: Auxiliary IPv4 or IPv6 addresses used by Network driver, as a mapping from hostname to IP

A full example:

ipam:
  driver: default
  config:
    - subnet: 172.28.0.0/16
      ip_range: 172.28.5.0/24
      gateway: 172.28.5.254
      aux_addresses:
        host1: 172.28.1.5
        host2: 172.28.1.6
        host3: 172.28.1.7

external

If set to true, specifies that this network has been created outside of Compose. docker-compose up will not attempt to create it, and will raise an error if it doesn’t exist.

external cannot be used in conjunction with other network configuration keys (driver, driver_opts, ipam).

version: '2'

services:
  proxy:
    build: ./proxy
    networks:
      - outside
      - default
  app:
    build: ./app
    networks:
      - default

networks:
  outside:
    external: true

You can also specify the name of the network separately from the name used to refer to it within the Compose file:

networks:
  outside:
    external:
      name: actual-name-of-network

Volume configuration reference

driver

Specify which volume driver should be used for this volume. Defaults to local. The Docker Engine will return an error if the driver is not available.

driver_opts

 driver_opts:
   foo: "bar"
   baz: 1

external

If set to true, specifies that this volume has been created outside of Compose. docker-compose up will not attempt to create it, and will raise an error if it doesn’t exist.

external cannot be used in conjunction with other volume configuration keys (driver, driver_opts).

version: '2'

services:
  db:
    image: postgres
    volumes:
      - data:/var/lib/postgresql/data

volumes:
  data:
    external: true

You can also specify the name of the volume separately from the name used to refer to it within the Compose file:

volumes:
  data:
    external:
      name: actual-name-of-volume

Дополнительно:  Word structure. Morphemic analysis of English words;
Оцените статью
Master Hi-technology
Добавить комментарий