← Назад к вопросам

Почему порт нужно экранировать в Docker compose?

2.0 Middle🔥 121 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему порт нужно экранировать в Docker Compose?

Порт нужно экранировать (заключать в кавычки) потому что YAML интерпретирует числовые значения как числа, а не как строки. Это может привести к неожиданному поведению и ошибкам при развёртывании.

Проблема: YAML парсинг

# НЕПРАВИЛЬНО — порт парсится как число
services:
  web:
    ports:
      - 8080:8080  # YAML интерпретирует как 8080 (число)
      - 5672:5672  # YAML интерпретирует как 5672 (число)

# ПРАВИЛЬНО — порт парсится как строка
services:
  web:
    ports:
      - "8080:8080"  # YAML интерпретирует как строка
      - "5672:5672"  # YAML интерпретирует как строка

Почему это проблема?

1. Специальные символы теряются

# Проблемный случай: порты с двоеточием
ports:
  - 8080:8080  # В YAML это может интерпретироваться неправильно

# YAML структурирует это как ключ-значение
# 8080 (ключ) : 8080 (значение)
# Результат: непредсказуемое поведение

# Правильно
ports:
  - "8080:8080"  # Уже строка, YAML не парсит

2. Порты, начинающиеся с 0

# Такие порты могут быть интерпретированы как восьмеричные!
ports:
  - 0644:8080  # YAML может рассмотреть 0644 как восьмеричное число!
              # 0644 (octal) = 420 (decimal)
              # Результат: неправильный порт

# Правильно
ports:
  - "0644:8080"  # Уже строка

Демонстрация YAML парсинга

import yaml

# Неправильный YAML
unquoted = """
services:
  web:
    ports:
      - 8080:8080
      - 0644:8080
"""

parsed = yaml.safe_load(unquoted)
print(parsed)
# {'services': {'web': {'ports': [{8080: 8080}, {0644: 8080}]}}}
# Видим, что это не строки, а числовые значения!

# Правильный YAML
quoted = """
services:
  web:
    ports:
      - "8080:8080"
      - "0644:8080"
"""

parsed = yaml.safe_load(quoted)
print(parsed)
# {'services': {'web': {'ports': ['8080:8080', '0644:8080']}}}
# Теперь это строки

Реальный Docker Compose пример

# docker-compose.yml

version: '3.8'

services:
  postgres:
    image: postgres:15
    ports:
      - "5432:5432"  # ОБЯЗАТЕЛЬНО в кавычках
    environment:
      POSTGRES_PASSWORD: secret

  redis:
    image: redis:7
    ports:
      - "6379:6379"  # ОБЯЗАТЕЛЬНО в кавычках

  web:
    build: .
    ports:
      - "8000:8000"  # ОБЯЗАТЕЛЬНО в кавычках
      - "8080:8080"  # ОБЯЗАТЕЛЬНО в кавычках
    depends_on:
      - postgres
      - redis

Что происходит без кавычек

# docker-compose.yml БЕЗ кавычек
services:
  api:
    ports:
      - 8080:8080  # Опасно!

# Результат при запуске
$ docker-compose up
# ERROR: service port must be a mapping, not a integer
# ИЛИ в некоторых версиях Docker
# ports: ['8080:8080']  # работает (случайно)
# ports: [8080]  # ошибка - неправильный формат

Нестабильность версий Docker Compose

# Docker Compose v1.x был более перекрывающим ошибки
# Иногда работал даже без кавычек

# Docker Compose v2.x (актуальный) более строг
ports:
  - 8080:8080  # Ошибка!
  - "8080:8080"  # Работает

Различные форматы портов

# Все эти форматы требуют кавычек
ports:
  # Стандартный формат
  - "8000:8000"
  
  # С указанием протокола
  - "8000:8000/tcp"
  - "8000:8000/udp"
  
  # Диапазоны портов
  - "8000-8010:8000-8010"
  
  # Только внутренний порт
  - "8000"
  
  # IP привязка
  - "127.0.0.1:8000:8000"
  - "0.0.0.0:8000:8000"

# БЕЗ кавычек любой из этих форматов может сломаться

Практическое следствие

# Скрипт, проверяющий корректный docker-compose.yml
#!/bin/bash

grep -E "^[[:space:]]*- [0-9]+:[0-9]+" docker-compose.yml && \
  echo "ОШИБКА: Порты не экранированы! Используй кавычки." && \
  exit 1

grep -E "^[[:space:]]*- \"[0-9]+:[0-9]+\"" docker-compose.yml && \
  echo "OK: Все порты экранированы"

Лучшие практики

# ✅ ПРАВИЛЬНЫЙ docker-compose.yml
version: '3.8'
services:
  db:
    image: postgres:15
    ports:
      - "5432:5432"  # ✓ В кавычках
    volumes:
      - postgres_data:/var/lib/postgresql/data

  app:
    build: .
    ports:
      - "8000:8000"  # ✓ В кавычках
      - "8000:8000/tcp"  # ✓ В кавычках
    depends_on:
      - db
    environment:
      DATABASE_URL: postgres://db:5432/mydb

volumes:
  postgres_data:

Вывод

Порт в Docker Compose нужно экранировать (класть в кавычки) потому что:

  1. YAML парсинг — числа без кавычек интерпретируются как числовые типы
  2. Двоеточие в строке — может парсится как ключ-значение в YAML
  3. Восьмеричные числа — порты с 0 спереди могут стать восьмеричными
  4. Стабильность — в Docker Compose v2 это требование строже
  5. Правильный формат — Docker ожидает строку, а не число

Просто всегда используй кавычки: - "8080:8080" и проблем не будет!