Docker для self-hosting

Каждый сервис в своём контейнере — изоляция, воспроизводимость, легко обновлять. Docker Compose описывает весь стек в одном файле.


Базовый docker-compose.yml

services:
  app:
    image: nginx:latest
    ports:
      - "localhost:80"    # только localhost!
    volumes:
      - ./data:/var/www        # данные на хосте
    restart: unless-stopped
    environment:
      - TZ=Asia/Yekaterinburg

Никогда не открывайте порты на 0.0.0.0 без необходимости

localhost:80 — порт открыт только на localhost. Снаружи — через reverse proxy ().


Сети

Docker создаёт bridge-сеть для каждого compose-проекта. Контейнеры в разных проектах не видят друг друга.

docker network connect app_default other-container
 
docker network inspect app_default

Volumes

volumes:
  - ./data:/app/data           # bind mount (файлы на хосте)
  - app_data:/app/data          # named volume (Docker управляет)

Bind mount удобнее для конфигов и данных, которые надо редактировать напрямую. Named volume — для данных, которыми Docker управляет сам (базы, кэши).


Права файлов

Docker пишет файлы от root. Если контейнер bind-mountит директорию, файлы на хосте могут стать root-owned.

sudo chown -R $USER:$USER ./data

Или указать user: "1000:1000" в compose (если контейнер это поддерживает).


Слои образа и кэш сборки

Каждая команда в Dockerfile создаёт новый слой. Docker кэширует результат — при повторном билде использует сохранённые слои.


Многосервисный стек

Для self-hosting почти всегда нужен минимум два сервиса. Compose создаёт общую сеть, и контейнеры общаются по именам сервисов через внутренний DNS.

services:
  app:
    build: .
    depends_on:
      - db
      - redis
    networks:
      - backend
    environment:
      DB_HOST: db
      REDIS_HOST: redis
 
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: <password>
    networks:
      - backend
 
  redis:
    image: redis:7-alpine
    networks:
      - backend
 
networks:
  backend:
    driver: bridge
  • db и redis доступны из app по именам хостов — Docker резолвит их сам.
  • Контейнеры не смотрят наружу — доступ через reverse proxy ().
  • Переменные подтягиваются из .env, который не попадает в образ.

Caddy reverse proxy

services:
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    restart: unless-stopped
 
volumes:
  caddy_data:
  caddy_config:

Caddy — современный reverse proxy с автоматическим TLS через Let’s Encrypt. Конфиг в Caddyfile — пара строк. Подробнее: .


Полезные команды

docker compose up -d              # запустить стек
docker compose down                # остановить и удалить
docker compose restart app         # перезапустить один сервис
docker compose logs -f app         # логи в реальном времени
docker exec -it container bash     # зайти в контейнер
docker system prune -a            # очистить всё неиспользуемое

Официальные образы

Всегда берите образы из официальных репозиториев (nginx, mariadb, caddy, python, postgres). Не используйте образы от неизвестных авторов — в них могут быть бэкдоры. Проверяйте тег и количество звёзд на Docker Hub.


Связанные статьи

  • — reverse proxy с авто-TLS
  • — синхронизация без облака
  • — статический сайт из Markdown
  • — self-hosted радио на Docker
  • — LLM inference в Docker

Связанные


← mrgnl