From 51fda6b732a5aa01b622925e59cbd457e44b5860 Mon Sep 17 00:00:00 2001 From: Michael Schiemer Date: Sun, 9 Nov 2025 00:29:20 +0100 Subject: [PATCH] fix: unify Docker registry URLs to localhost:5000 - Change docker-compose.staging.yml: git.michaelschiemer.de:5000 -> localhost:5000 - Update deploy-image.yml playbook to: - Pull images from registry.michaelschiemer.de (source registry) - Tag and push to localhost:5000 (local registry) for local containers - Remove hardcoded git.michaelschiemer.de:5000 logic - Use local_registry from compose files for deployment This ensures: - Workflow pushes to registry.michaelschiemer.de (external, HTTPS) - Containers use localhost:5000 (local, faster, no HTTPS overhead) - Consistent registry usage across staging and production --- deployment/ansible/playbooks/deploy-image.yml | 75 +++++++++++-------- docker-compose.staging.yml | 26 ++++--- 2 files changed, 59 insertions(+), 42 deletions(-) diff --git a/deployment/ansible/playbooks/deploy-image.yml b/deployment/ansible/playbooks/deploy-image.yml index 0c451789..65c3c966 100644 --- a/deployment/ansible/playbooks/deploy-image.yml +++ b/deployment/ansible/playbooks/deploy-image.yml @@ -47,18 +47,26 @@ grep -h "image:" docker-compose.base.yml docker-compose.{{ application_compose_suffix }} 2>/dev/null | \ grep -E "{{ app_name }}" | head -1 | \ sed -E 's/.*image:\s*([^\/]+).*/\1/' | \ - sed -E 's/\/.*$//' || echo "{{ docker_registry }}" + sed -E 's/\/.*$//' || echo "localhost:5000" register: compose_registry_url changed_when: false failed_when: false - - name: Set actual registry from compose file or use default + - name: Set local registry (where containers expect the image) ansible.builtin.set_fact: - actual_registry: "{{ (compose_registry_url.stdout | trim) if (compose_registry_url.stdout | trim != '' and compose_registry_url.stdout | trim != docker_registry) else docker_registry }}" + local_registry: "{{ (compose_registry_url.stdout | trim) if (compose_registry_url.stdout | trim != '') else 'localhost:5000' }}" - - name: Set deploy_image from actual registry, app_name and tag + - name: Set source registry (where workflow pushes the image) ansible.builtin.set_fact: - deploy_image: "{{ actual_registry }}/{{ app_name }}:{{ image_tag }}" + source_registry: "{{ docker_registry }}" + + - name: Set deploy_image from source registry (for pulling) + ansible.builtin.set_fact: + deploy_image: "{{ source_registry }}/{{ app_name }}:{{ image_tag }}" + + - name: Set local_image (where containers expect the image) + ansible.builtin.set_fact: + local_image: "{{ local_registry }}/{{ app_name }}:{{ image_tag }}" - name: Set database and MinIO variables from vault or defaults ansible.builtin.set_fact: @@ -135,10 +143,30 @@ register: image_info failed_when: image_info.failed | default(false) + - name: Tag image for local registry (if source and local registry differ) + community.docker.docker_image: + name: "{{ deploy_image }}" + repository: "{{ local_image }}" + tag: "{{ image_tag }}" + source: local + when: source_registry != local_registry + register: image_tag_result + + - name: Push image to local registry (if source and local registry differ) + community.docker.docker_image: + name: "{{ local_image }}" + push: true + source: local + when: + - source_registry != local_registry + - image_tag_result.changed | default(false) + ignore_errors: yes + failed_when: false + - name: Update docker-compose file with new image tag ansible.builtin.replace: path: "{{ application_code_dest }}/docker-compose.{{ application_compose_suffix }}" - regexp: '^(\s+image:\s+)({{ actual_registry }}/{{ app_name }}:)(.*)$' + regexp: '^(\s+image:\s+)({{ local_registry }}/{{ app_name }}:)(.*)$' replace: '\1\2{{ image_tag }}' register: compose_update_result failed_when: false @@ -148,7 +176,7 @@ ansible.builtin.replace: path: "{{ application_code_dest }}/docker-compose.{{ application_compose_suffix }}" regexp: '^(\s+image:\s+)([^\/]+\/{{ app_name }}:)(.*)$' - replace: '\1{{ actual_registry }}/{{ app_name }}:{{ image_tag }}' + replace: '\1{{ local_registry }}/{{ app_name }}:{{ image_tag }}' register: compose_update_alt when: compose_update_result.changed == false failed_when: false @@ -211,11 +239,9 @@ set_fact: insecure_registries_list: >- {%- set existing = docker_daemon_config_dict.get('insecure-registries', []) | list -%} - {%- if 'git.michaelschiemer.de:5000' not in existing -%} - {{ existing + ['git.michaelschiemer.de:5000'] }} - {%- else -%} - {{ existing }} - {%- endif -%} + {%- set needed_registries = [local_registry] | list -%} + {%- set all_registries = (existing + needed_registries) | unique | list -%} + {{ all_registries }} - name: Merge insecure registry into Docker daemon config set_fact: @@ -248,28 +274,13 @@ ignore_errors: yes changed_when: false - - name: Extract registry URLs with ports from docker-compose files - ansible.builtin.shell: | - cd {{ application_code_dest }} - grep -h "image:" docker-compose.base.yml docker-compose.{{ application_compose_suffix }} 2>/dev/null | \ - sed -E 's/.*image:\s*([^\/]+).*/\1/' | \ - sed -E 's/\/.*$//' | \ - sort -u || echo "" - register: actual_registry_urls_full - changed_when: false - failed_when: false - - - name: Set list of registries to login to (filter out service names, preserve ports) + - name: Set list of registries to login to (source registry for pulling, local registry for pushing) ansible.builtin.set_fact: registries_to_login: >- - {%- set found_registries = actual_registry_urls_full.stdout | trim | split('\n') | select('match', '.+') | list -%} - {%- set filtered_registries = found_registries | select('match', '.*\.(de|com|org|net|io|dev)(:[0-9]+)?$|^[^:]+:[0-9]+$|^localhost(:[0-9]+)?$') | list -%} - {%- set default_registry = [docker_registry] -%} - {%- if filtered_registries | length > 0 -%} - {{ filtered_registries | unique | list }} - {%- else -%} - {{ default_registry }} - {%- endif -%} + {%- set source_list = [source_registry] if source_registry != local_registry else [] -%} + {%- set local_list = [local_registry] -%} + {%- set all_registries = source_list + local_list -%} + {{ all_registries | unique | list }} - name: Login to all Docker registries before compose up community.docker.docker_login: diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml index 6c44e4ab..776155e5 100644 --- a/docker-compose.staging.yml +++ b/docker-compose.staging.yml @@ -11,11 +11,12 @@ services: # PHP-FPM Application Runtime staging-app: - image: git.michaelschiemer.de:5000/framework:latest + image: localhost:5000/framework:latest container_name: staging-app restart: unless-stopped networks: - staging-internal + - postgres-staging-internal environment: - TZ=Europe/Berlin - APP_ENV=staging @@ -28,8 +29,8 @@ services: - GIT_TOKEN=${GIT_TOKEN:-} - GIT_USERNAME=${GIT_USERNAME:-} - GIT_PASSWORD=${GIT_PASSWORD:-} - # Database (can share with production or use separate) - - DB_HOST=${DB_HOST:-postgres} + # Database - using separate staging database + - DB_HOST=${DB_HOST:-postgres-staging} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE:-michaelschiemer_staging} - DB_USERNAME=${DB_USERNAME} @@ -208,7 +209,7 @@ services: condition: service_started # Nginx Web Server staging-nginx: - image: git.michaelschiemer.de:5000/framework:latest + image: localhost:5000/framework:latest container_name: staging-nginx restart: unless-stopped networks: @@ -344,17 +345,18 @@ services: # Queue Worker (Background Jobs) staging-queue-worker: - image: git.michaelschiemer.de:5000/framework:latest + image: localhost:5000/framework:latest container_name: staging-queue-worker restart: unless-stopped networks: - staging-internal + - postgres-staging-internal environment: - TZ=Europe/Berlin - APP_ENV=staging - APP_DEBUG=${APP_DEBUG:-true} - # Database (can share with production or use separate) - - DB_HOST=${DB_HOST:-postgres} + # Database - using separate staging database + - DB_HOST=${DB_HOST:-postgres-staging} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE:-michaelschiemer_staging} - DB_USERNAME=${DB_USERNAME} @@ -399,17 +401,18 @@ services: # Scheduler (Cron Jobs) staging-scheduler: - image: git.michaelschiemer.de:5000/framework:latest + image: localhost:5000/framework:latest container_name: staging-scheduler restart: unless-stopped networks: - staging-internal + - postgres-staging-internal environment: - TZ=Europe/Berlin - APP_ENV=staging - APP_DEBUG=${APP_DEBUG:-true} - # Database (can share with production or use separate) - - DB_HOST=${DB_HOST:-postgres} + # Database - using separate staging database + - DB_HOST=${DB_HOST:-postgres-staging} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE:-michaelschiemer_staging} - DB_USERNAME=${DB_USERNAME} @@ -471,6 +474,9 @@ networks: external: true staging-internal: driver: bridge + postgres-staging-internal: + external: true + name: postgres-staging-internal app-internal: external: true name: app-internal