Files
mypointvpn/src/serverus/playbooks/docker.yml
T
protokeyandClaude Opus 5.5 fd4b05097a feat: публикация портов не-HTTP сервисами, проверка портов до деплоя, пример RustDesk
serverus: app_ports.py проверяет опубликованные порты приложения до
изменений - по docker compose config (переменные из .env подставлены)
против слушающих сокетов сервера и портов контейнеров других приложений.
Занятый порт больше не роняет up после замены файлов. Конвенция: только
мост; не-HTTP сервисы публикуют свои порты, 80 и 443 - у caddy;
bind-mount только своих файлов из data/<сервис>/ с :ro. Описано, что
упавший up после синхронизации файлы не откатывает.

App: uploads.check предупреждает о 80/443 вместо любых портов и о
bind-mount из папки приложения вне data/ или без :ro.

docs/apps/rustdesk: приложение (hbbs, hbbr, ключ генерируем сами),
genkey.py и check.py - проверка сервера по протоколу RustDesk снаружи.
Проверено на стенде Debian 13: деплой, повторный деплой, отказ второго
приложения на тех же портах до изменений, перезагрузка сервера.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:31:38 +04:00

136 lines
5.1 KiB
YAML

# extravars: apps_dir, caddy_image, local_certs
#
# Docker из репозитория Docker, логи контейнеров с ротацией, автоматические обновления безопасности, папка приложений,
# сеть web и ingress: приложение caddy, которое публикует 80 и 443. Caddy подключает блоки приложений
# из data/caddy/sites/ и сам выпускает сертификаты для их доменов. local_certs - сертификаты своего CA Caddy.
# Фаервол настраивается первым: nftables при старте стирает все правила, Docker ставит свои поверх.
- name: Install Docker platform
hosts: target
gather_facts: true
vars:
caddy_dir: "{{ apps_dir }}/caddy"
tasks:
- ansible.builtin.import_tasks: tasks/firewall.yml
vars:
firewall_tcp_ports: [ "{{ ansible_port }}", 80, 443 ]
firewall_udp_ports: [ 443 ]
# трафик контейнеров идет через forward: его фильтрует Docker
firewall_forward: true
- name: Install prerequisites
ansible.builtin.apt:
name: [ ca-certificates, curl, python3, unattended-upgrades ]
state: present
update_cache: true
- name: Enable automatic security updates
ansible.builtin.copy:
dest: /etc/apt/apt.conf.d/20auto-upgrades
mode: "0644"
content: |
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
- name: Create keyrings directory
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: "0755"
- name: Download Docker key
ansible.builtin.get_url:
url: https://download.docker.com/linux/debian/gpg
dest: /etc/apt/keyrings/docker.asc
mode: "0644"
- name: Add Docker repository
ansible.builtin.copy:
dest: /etc/apt/sources.list.d/docker.sources
mode: "0644"
content: |
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: {{ ansible_facts.distribution_release }}
Components: stable
Architectures: {{ 'arm64' if ansible_facts.architecture == 'aarch64' else 'amd64' }}
Signed-By: /etc/apt/keyrings/docker.asc
- name: Create Docker config directory
ansible.builtin.file:
path: /etc/docker
state: directory
mode: "0755"
- name: Configure Docker daemon
ansible.builtin.copy:
dest: /etc/docker/daemon.json
mode: "0644"
content: |
{
"log-driver": "local",
"log-opts": {"max-size": "10m", "max-file": "3"}
}
register: docker_daemon
- name: Install Docker
ansible.builtin.apt:
name: [ docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin, docker-compose-plugin ]
state: present
update_cache: true
# после частых перезапусков (фаервол, release) systemd может держать Docker остановленным по лимиту запусков
- name: Reset Docker start limit
ansible.builtin.command: systemctl reset-failed docker.service
changed_when: false
failed_when: false
- name: Start Docker
ansible.builtin.systemd_service:
name: docker
enabled: true
state: "{{ 'restarted' if docker_daemon.changed else 'started' }}"
- name: Create apps directory
ansible.builtin.file:
path: "{{ apps_dir }}"
state: directory
mode: "0700"
- name: Create web network
ansible.builtin.shell: docker network inspect web >/dev/null 2>&1 || { docker network create web && echo created; }
register: web_network
changed_when: "'created' in web_network.stdout"
- name: Create ingress directories
ansible.builtin.file:
path: "{{ caddy_dir }}/data/caddy/sites"
state: directory
mode: "0700"
- name: Write ingress compose file
ansible.builtin.template:
src: templates/caddy-compose.yaml.j2
dest: "{{ caddy_dir }}/docker-compose.yaml"
mode: "0600"
# Caddyfile смонтирован папкой: файл, замененный целиком, контейнер увидел бы только после пересоздания
- name: Write Caddyfile
ansible.builtin.template:
src: templates/Caddyfile.j2
dest: "{{ caddy_dir }}/data/caddy/Caddyfile"
mode: "0644"
register: caddyfile
- name: Start ingress
ansible.builtin.command: docker compose up -d --remove-orphans
args:
chdir: "{{ caddy_dir }}"
register: caddy_up
changed_when: "'Started' in caddy_up.stderr or 'Recreated' in caddy_up.stderr"
- name: Reload Caddyfile
ansible.builtin.command: docker compose exec -T caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
args:
chdir: "{{ caddy_dir }}"
when: caddyfile.changed and not caddy_up.changed