Как развернуть одну и ту же композицию в разных стеках и автоматически адаптировать имена контейнеров?

#docker #docker-compose

Вопрос:

Я пытаюсь создать docker-compose.yml файл, который позволит мне легко запускать среды для разработки внутри. Иногда мне хотелось бы иметь 2 или более из них одновременно, но я делаю это наивно ERROR: for pdb Cannot create container for service pdb: Conflict. The container name "/pdb" is already in use by container ... (даже если они находятся в разных стеках).

 version: '3.4'

services:

  pdb:
    hostname: "pdb"
    container_name: "pdb"
    image: "postgres:latest"

(...other services...)
 

Есть ли способ автоматически называть их различимым, но систематическим способом? Например, что-то вроде этого:

 version: '3.4'

services:

  pdb:
    hostname: "${stack_name}_pdb"
    container_name: "${stack_name}_pdb"
    image: "postgres:latest"

(...other services...)
 

РЕДАКТИРОВАТЬ: По-видимому, это несколько специфичный для службы вопрос, поэтому на всякий случай приведу полный файл компоновки…

 version: '3.4'

services:

  rmq:
    hostname: "rmq"
    container_name: "rmq"
    image: "rabbitmq:latest"
    networks:
      - "fakenet"
    ports:
      - "5672:5672"
    healthcheck:
      test: "rabbitmq-diagnostics -q ping"
      interval: 30s
      timeout: 30s
      retries: 3

  pdb:
    hostname: "pdb"
    container_name: "pdb"
    image: "postgres:latest"
    networks:
      - "fakenet"
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: ******
      POSTGRES_USER: postgres
      POSTGRES_DB: test_db
    volumes:
      - "./deploy/pdb:/docker-entrypoint-initdb.d"
      - "./data/dbase:/var/lib/postgresql/data"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 10s
      timeout: 5s
      retries: 5

  workenv:
    hostname: "aiida"
    container_name: "aiida"
    image: "aiida_workenv:v0.1"
    expose:
      - "8888" # AiiDa Lab
      - "8890" # Jupyter Lab
      - "5000" # REST API
    ports: # local:container
      - 8888:8888
      - 8890:8890
      - 5000:5000
    volumes:
      - "./data/codes:/home/devuser/codes"
      - "./data/aiida:/home/devuser/.aiida"
    depends_on:
      pdb:
        condition: service_healthy
      rmq:
        condition: service_healthy
    networks:
      - "fakenet"
    environment:
      LC_ALL: "en_US.UTF-8"
      LANG: "en_US.UTF-8"
      PSQL_HOST: "pdb"
      PSQL_PORT: "5432"
    command: "tail -f /dev/null"

networks:
  fakenet:
    driver: bridge

 

Ответ №1:

Просто вообще не устанавливайте вручную container_name: . Compose автоматически назначит имя на основе текущего названия проекта. Аналогично, вам обычно не нужно устанавливать hostname: (RabbitMQ-одно очень специфическое исключение, если вы его используете).

Если вам действительно нужно опубликовать порты из настройки Compose, чтобы иметь возможность получить к ним доступ из хост-системы, другой очевидный недостаток заключается в том, что первый ports: номер должен быть уникальным для всего хоста. Вы можете указать один номер ports: , чтобы Docker мог выбрать порт хоста, хотя вам нужно будет посмотреть его позже docker-compose port .

 version: '3.8'
services:
  pdb:
    image: "postgres:latest"
    # no hostname: or ports:

  app:
    build: .
    environment:
      PGHOST: pdb
    ports:
      - 3000 # container-side port, Docker picks host port
 
 docker-compose -p myname -d up
docker-compose -p myname port app 3000
 

Комментарии:

1. Эй, @David Maze, спасибо за ответ, PGHOST: pdb пример помог мне немного лучше понять, как обращаться с этой услугой. Таким образом, мне не нужно предоставлять порты для контейнеров для связи друг с другом, только для внешнего доступа? Тем не менее, я использую RabbitMQ в качестве второго сервиса =( [см. Обновленный пост]. В чем проблема с этим? Нужна ли мне какая-либо осторожность при выборе имени хоста? Моя настройка в настоящее время работает для 1 развертывания, но я не сделал ничего особенного…

2. Обычно контейнер видит свой идентификатор контейнера как свое имя хоста. RabbitMQ, в частности, хранит данные в каталоге, названном именем хоста, поэтому, если вы перезапустите RabbitMQ в новом контейнере с другим именем хоста, он не найдет данные старого контейнера. Поэтому специально для RabbitMQ вам нужно установить hostname: некоторую фиксированную строку, но не имеет большого значения, что это такое, и это вообще не связано с подключением между контейнерами.

3. Последующий вопрос: если я позволю докеру выбрать порты хоста, как я узнаю, какие из них были выбраны? Например, мне нужно передать их в другую службу, чтобы взаимодействовать как с postgres, так и с rmq, и чтобы я мог проверять записные книжки, которые работают внутри нее, снаружи.

4. docker-compose port говорит тебе.