feat: docker-серверы - приложения в ~/apps под управлением бота
serverus: DockerHost - установка Docker и ingress Caddy, deploy приложения с проверкой compose и caddy.conf до изменений и пересозданием только изменившихся сервисов, status, control, logs, remove. nftables перезапускается только при изменении конфига, Docker следом восстанавливает свои правила; release восстанавливает конфиг Debian вместо остановки nftables. Telegram: прием документов и отправка файлов, раздача файлов своего Bot API сервера через nginx (telegram-files). App: общая модель Managed для Point и Platform, DockerApp и версии файлов AppVersion, разбор архивов (uploads), сценарии платформы (platforms), задачи и меню docker-серверов в боте. Проверено на стенде Debian 13 с local_certs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
65c19ea1cd
commit
a8d1f286d1
42 files changed
+3509
-232
No files matched your search
@@ -0,0 +1,135 @@
|
||||
# extravars: apps_dir, caddy_image, local_certs
|
||||
#
|
||||
# Docker из репозитория Docker, логи контейнеров с ротацией, автоматические обновления безопасности, папка приложений,
|
||||
# сеть web и ingress: приложение caddy, единственное, которое публикует порты. 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
|
||||
Reference in new issue
Block a user