Docker. Является ли сопоставление томов файла сокета поведением переопределения?

Ниже приведен фрагмент кода изображения jenkins, взятого из здесь:

# Install Docker Engine
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D && \
    echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | tee /etc/apt/sources.list.d/docker.list && \
    apt-get update -y && \
    apt-get purge lxc-docker* -y && \
    apt-get install docker-engine=${DOCKER_ENGINE:-1.10.2}-0~trusty -y && \
    usermod -aG docker jenkins && \
    usermod -aG users jenkins

который устанавливает движок докера в образ jenkins. Насколько я понимаю, var/run/docker.sock создается в контейнере Jenkins из-за установки механизма докера.


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

volumes:
  - jenkins_home:/var/jenkins_home
  - /var/run/docker.sock:/var/run/docker.sock

который запускает контейнер jenkins (выше) на хосте EC2.

На хосте EC2 также запущен демон Docker.

Итак, на хосте EC2 работает демон docker. В докер-контейнере также работает демон докеров (Дженкинс).


С этим синтаксисом (/var/run/docker.sock:/var/run/docker.sock) в docker-compose (выше) для файлов сокетов,

Демон докера в контейнере Jenkins переопределяет свой собственный файл сокета файлом сокета, присутствующим на хосте EC2? Если да... каковы его последствия?


person overexchange    schedule 02.11.2019    source источник


Ответы (2)


Из документов:

Docker-engine — клиент-серверное приложение

Обратите внимание, что при установке docker-engine вы устанавливаете docker-daemon (сервер) и docker cli (клиент).

Это означает, что если демон docker не запущен, вы все равно сможете запускать команды docker cli:

docker info
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

Образ Jenkins, которым вы поделились, не содержит инструкций по запуску механизма Docker. Поэтому я предполагаю, что он не работает внутри контейнера.

/var/run/docker.sock:/var/run/docker.sock том сопоставляет сокет механизма докера узла докера с контейнером.

Таким образом, команды docker cli, запускаемые внутри контейнера, управляют механизмом докеров, работающим на хосте докеров.

Это имеет смысл, если вы выполняете CI/CD на своем хосте из контейнерного Jenkins.

Конвейеры Jenkins могут использовать команды docker, docker-compose и docker swarm для запуска тестов, создания артефактов и развертывания новых версий приложений.

person rok    schedule 02.11.2019

/var/run/docker.sock в контейнере — это сокет Docker хоста и ничего больше. Это потому что:

  1. Контейнер Docker не запускает никаких программ, кроме тех, которые явно запущены в его точке входа и/или команде, и это почти всегда просто одна прикладная программа.
  2. Вероятно, вы не собираетесь запускать демон Docker, поэтому он установлен, но не запущен.
  3. Файлы сокетов Unix не будут созданы до тех пор, пока не запустится демон и привяжет(2) сокет к конкретному файлу.
  4. Параметр docker run -v всегда будет «проталкивать» содержимое хоста в контейнер, и это происходит до запуска любого из процессов контейнера.

Таким образом, в описываемом вами сценарии это не может быть ничего, кроме сокета Docker хоста, потому что второго демона Docker нет.


Скажем ради аргумента, что вы на самом деле таким образом запускаете второго демона.

Порядок операций здесь следующий: (1) Docker настраивает файловую систему контейнера, (2) Docker запускает точку входа, (3) точка входа запускает демон, (4) демон пытается создать файл сокета. В момент запуска демона его файл сокета уже будет существовать. Я полагаю, что это приведет к сбою вызова bind(2) с EADDRINUSE, и демон не запустится. Надеюсь, это приведет к сбою запуска вашего контейнера.

Вы могли бы законно запустить демона в контейнере, который публикует сокет Unix, к которому вы хотите получить доступ с хоста. Чтобы это работало, вам нужно смонтировать каталог в контейнер и указать на него демону. Вероятно, это не может быть /var/run с любой стороны (на хосте /var/run много всего; монтирование каталога скрывает существующее содержимое в контейнере, и вы также можете захотеть /var/run контейнера). Это должен быть каталог, а не имя файла сокета, поскольку Docker создаст пустой каталог, если он не существует; что-то будет существовать в контейнере по этому пути, и привязка завершится ошибкой.

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

docker run \
  --name foo \                   # container name
  -v $PWD/socket:/socket \       # bind mount a directory
  foo \                          # image name
  food \                         # command to run in the container
    --foreground \               # don't daemonize; keep the container alive
    --bind fd://socket/foo.sock  # put the socket in the shared directory

На хосте вам нужно установить FOO_SOCKET_PATH=$PWD/socket/foo.sock или иным образом указать на этот конкретный файл.

person David Maze    schedule 02.11.2019