D5.3 Private Registry ฮผฮต Ansible ๐๏ธ
ฮคฮน ฮธฮฑ ฯฯฮนฮฌฮพฮฟฯ ฮผฮต
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Private Docker Registry โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ nextcloud (registry server) โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ registry:2 โ โ nginx (SSL/Auth) โ โ โ
โ โ โ :5000 (internal) โ โ :443 (external) โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ /opt/registry/ โ โ
โ โ โโโ data/ โ image storage โ โ
โ โ โโโ auth/ โ htpasswd โ โ
โ โ โโโ certs/ โ SSL certificates โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Clients: โ
โ docker login registry.example.com โ
โ docker push registry.example.com/myapp:1.0.0 โ
โ docker pull registry.example.com/myapp:1.0.0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ฮฮฟฮผฮฎ Role
# ฮฮทฮผฮนฮฟฯ
ฯฮณฮฏฮฑ registry role
cd ~/ansible/roles
ansible-galaxy role init registry
tree ~/ansible/roles/registry/
# registry/
# โโโ defaults/
# โ โโโ main.yml
# โโโ handlers/
# โ โโโ main.yml
# โโโ tasks/
# โ โโโ main.yml
# โ โโโ setup.yml
# โ โโโ auth.yml
# โ โโโ deploy.yml
# โ โโโ verify.yml
# โโโ templates/
# โโโ registry-compose.yml.j2
# โโโ nginx-registry.conf.j2
defaults/main.yml
cat > ~/ansible/roles/registry/defaults/main.yml << 'EOF'
---
# ============================================================
# Private Registry Defaults
# ============================================================
# โโ Registry Settings โโโโโโโโโโโโโโโโโโโโโโโโโ
registry_name: registry
registry_port: 5000 # internal port
registry_ext_port: 443 # external port (SSL)
registry_hostname: "{{ inventory_hostname }}"
# โโ Storage โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry_base_dir: /opt/registry
registry_data_dir: /opt/registry/data
registry_auth_dir: /opt/registry/auth
registry_certs_dir: /opt/registry/certs
registry_logs_dir: /opt/registry/logs
# โโ Authentication โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry_auth_enabled: true
registry_users: []
# Format:
# - username: myuser
# password: "{{ vault_registry_pass }}"
# โโ SSL โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry_ssl_enabled: true
registry_ssl_self_signed: true # โ true ฮณฮนฮฑ self-signed
registry_ssl_cert_days: 3650 # 10 ฯฯฯฮฝฮนฮฑ
# โโ Images โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry_image: registry:2
nginx_image: nginx:1.25.3-alpine
# โโ Resources โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry_memory: "256m"
registry_cpus: "0.25"
nginx_memory: "64m"
nginx_cpus: "0.25"
# โโ Garbage Collection โโโโโโโโโโโโโโโโโโโโโโโโ
registry_gc_enabled: true
registry_gc_schedule: "0 2 * * 0" # ฮฯ
ฯฮนฮฑฮบฮฎ 02:00
EOF
tasks/main.yml
cat > ~/ansible/roles/registry/tasks/main.yml << 'EOF'
---
# ============================================================
# Private Registry โ Main Entry Point
# ============================================================
- name: Setup registry infrastructure
ansible.builtin.import_tasks:
file: setup.yml
tags: [setup, registry]
- name: Configure authentication
ansible.builtin.import_tasks:
file: auth.yml
tags: [auth, registry]
- name: Deploy registry
ansible.builtin.import_tasks:
file: deploy.yml
tags: [deploy, registry]
- name: Verify registry
ansible.builtin.import_tasks:
file: verify.yml
tags: [verify, registry]
EOF
tasks/setup.yml
cat > ~/ansible/roles/registry/tasks/setup.yml << 'EOF'
---
# ============================================================
# Registry Setup โ Directories & Certificates
# ============================================================
# โโ Directories โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Create registry directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: root
group: root
loop:
- "{{ registry_base_dir }}"
- "{{ registry_data_dir }}"
- "{{ registry_auth_dir }}"
- "{{ registry_certs_dir }}"
- "{{ registry_logs_dir }}"
# โโ Self-signed SSL certificate โโโโโโโโโโโโโโโ
- name: Generate self-signed SSL certificate
ansible.builtin.command:
cmd: >
openssl req -newkey rsa:4096 -nodes -sha256
-keyout {{ registry_certs_dir }}/registry.key
-x509
-days {{ registry_ssl_cert_days }}
-out {{ registry_certs_dir }}/registry.crt
-subj "/CN={{ registry_hostname }}"
-addext "subjectAltName=DNS:{{ registry_hostname }},IP:{{ ansible_facts['default_ipv4']['address'] }}"
args:
creates: "{{ registry_certs_dir }}/registry.crt"
when: registry_ssl_self_signed
register: cert_created
- name: Set certificate permissions
ansible.builtin.file:
path: "{{ item.path }}"
mode: "{{ item.mode }}"
loop:
- path: "{{ registry_certs_dir }}/registry.crt"
mode: '0644'
- path: "{{ registry_certs_dir }}/registry.key"
mode: '0600'
when: registry_ssl_self_signed
# โโ Trust certificate (ฮณฮนฮฑ Docker) โโโโโโโโโโโโ
- name: Create Docker certs directory
ansible.builtin.file:
path: "/etc/docker/certs.d/{{ registry_hostname }}:{{ registry_ext_port }}"
state: directory
mode: '0755'
- name: Copy certificate to Docker certs
ansible.builtin.copy:
src: "{{ registry_certs_dir }}/registry.crt"
dest: "/etc/docker/certs.d/{{ registry_hostname }}:{{ registry_ext_port }}/ca.crt"
remote_src: true
mode: '0644'
# โโ Install htpasswd tool โโโโโโโโโโโโโโโโโโโโโ
- name: Install apache2-utils (ฮณฮนฮฑ htpasswd)
ansible.builtin.apt:
name: apache2-utils
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Install httpd-tools (ฮณฮนฮฑ htpasswd)
ansible.builtin.dnf:
name: httpd-tools
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: Install apache2-utils (openSUSE)
community.general.zypper:
name: apache2-utils
state: present
when: ansible_facts['os_family'] == "Suse"
EOF
tasks/auth.yml
cat > ~/ansible/roles/registry/tasks/auth.yml << 'EOF'
---
# ============================================================
# Registry Authentication โ htpasswd
# ============================================================
# โโ ฮฮทฮผฮนฮฟฯ
ฯฮณฮฏฮฑ htpasswd ฮฑฯฯฮตฮฏฮฟฯ
โโโโโโโโโโโโโโโ
- name: Create htpasswd file
ansible.builtin.file:
path: "{{ registry_auth_dir }}/htpasswd"
state: touch
mode: '0600'
owner: root
when: registry_users | length == 0
# โโ ฮ ฯฮฟฯฮธฮฎฮบฮท users โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Add registry users
ansible.builtin.command:
cmd: >
htpasswd
{% if not htpasswd_stat.stat.exists %}
-Bbc
{% else %}
-Bb
{% endif %}
{{ registry_auth_dir }}/htpasswd
{{ item.username }}
{{ item.password }}
loop: "{{ registry_users }}"
loop_control:
label: "{{ item.username }}"
no_log: true
register: htpasswd_result
vars:
htpasswd_stat:
stat:
exists: true
- name: Check htpasswd file
ansible.builtin.stat:
path: "{{ registry_auth_dir }}/htpasswd"
register: htpasswd_file
- name: Set htpasswd permissions
ansible.builtin.file:
path: "{{ registry_auth_dir }}/htpasswd"
mode: '0600'
owner: root
when: htpasswd_file.stat.exists
- name: Show auth status
ansible.builtin.debug:
msg: >
Registry auth:
{{ 'โ
' + (registry_users | length | string) + ' users configured'
if registry_users | length > 0
else 'โ ๏ธ No users configured!' }}
EOF
tasks/deploy.yml
cat > ~/ansible/roles/registry/tasks/deploy.yml << 'EOF'
---
# ============================================================
# Registry Deployment ฮผฮต Docker Compose
# ============================================================
# โโ Render compose file โโโโโโโโโโโโโโโโโโโโโโโ
- name: Render registry docker-compose.yml
ansible.builtin.template:
src: registry-compose.yml.j2
dest: "{{ registry_base_dir }}/docker-compose.yml"
mode: '0644'
# โโ Render nginx config โโโโโโโโโโโโโโโโโโโโโโโ
- name: Render nginx configuration
ansible.builtin.template:
src: nginx-registry.conf.j2
dest: "{{ registry_base_dir }}/nginx.conf"
mode: '0644'
# โโ Pull images โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Pull registry images
community.docker.docker_image:
name: "{{ item.name }}"
tag: "{{ item.tag }}"
source: pull
loop:
- { name: registry, tag: "2" }
- { name: nginx, tag: "1.25.3-alpine" }
loop_control:
label: "{{ item.name }}:{{ item.tag }}"
# โโ Deploy stack โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Deploy registry stack
community.docker.docker_compose_v2:
project_src: "{{ registry_base_dir }}"
project_name: "{{ registry_name }}"
state: present
register: registry_deploy
# โโ Wait for registry โโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Wait for registry to start
community.docker.docker_container_info:
name: "{{ registry_name }}_registry"
register: reg_info
until: >
reg_info.container is defined and
reg_info.container.State.Running == true
retries: 12
delay: 5
# โโ Wait for nginx โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Wait for nginx proxy to start
community.docker.docker_container_info:
name: "{{ registry_name }}_nginx"
register: nginx_info
until: >
nginx_info.container is defined and
nginx_info.container.State.Running == true
retries: 6
delay: 5
# โโ Setup garbage collection โโโโโโโโโโโโโโโโโโ
- name: Deploy registry GC script
ansible.builtin.copy:
dest: /usr/local/bin/registry-gc.sh
mode: '0755'
owner: root
content: |
#!/bin/bash
# Registry Garbage Collection
echo "=== Registry GC $(date) ==="
docker compose \
-f {{ registry_base_dir }}/docker-compose.yml \
-p {{ registry_name }} \
exec -T registry \
registry garbage-collect \
/etc/docker/registry/config.yml
echo "=== GC complete ==="
when: registry_gc_enabled
- name: Schedule registry GC
ansible.builtin.cron:
name: "Registry garbage collection"
minute: "{{ registry_gc_schedule.split()[0] }}"
hour: "{{ registry_gc_schedule.split()[1] }}"
day: "{{ registry_gc_schedule.split()[2] }}"
month: "{{ registry_gc_schedule.split()[3] }}"
weekday: "{{ registry_gc_schedule.split()[4] }}"
user: root
job: "/usr/local/bin/registry-gc.sh >> /var/log/registry-gc.log 2>&1"
state: present
when: registry_gc_enabled
EOF
templates/registry-compose.yml.j2
cat > ~/ansible/roles/registry/templates/registry-compose.yml.j2 << 'EOF'
{# Private Registry Docker Compose #}
{# Managed by Ansible โ DO NOT EDIT! #}
version: "3.8"
services:
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# REGISTRY โ Storage Backend
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
registry:
image: {{ registry_image }}
container_name: {{ registry_name }}_registry
restart: unless-stopped
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
REGISTRY_HTTP_SECRET: {{ vault_registry_http_secret }}
{% if registry_auth_enabled %}
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: "Registry Realm"
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
{% endif %}
REGISTRY_STORAGE_DELETE_ENABLED: "true"
volumes:
- {{ registry_data_dir }}:/var/lib/registry
- {{ registry_auth_dir }}:/auth:ro
- /etc/localtime:/etc/localtime:ro
networks:
- registry_net
deploy:
resources:
limits:
memory: {{ registry_memory }}
cpus: "{{ registry_cpus }}"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "--no-check-certificate", "http://localhost:5000/v2/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# NGINX โ SSL Proxy
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
nginx:
image: {{ nginx_image }}
container_name: {{ registry_name }}_nginx
restart: unless-stopped
ports:
- "{{ registry_ext_port }}:443"
volumes:
- {{ registry_base_dir }}/nginx.conf:/etc/nginx/nginx.conf:ro
- {{ registry_certs_dir }}:/etc/nginx/certs:ro
- {{ registry_logs_dir }}:/var/log/nginx
- /etc/localtime:/etc/localtime:ro
networks:
- registry_net
depends_on:
registry:
condition: service_healthy
deploy:
resources:
limits:
memory: {{ nginx_memory }}
cpus: "{{ nginx_cpus }}"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "--no-check-certificate", "https://localhost/v2/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
networks:
registry_net:
name: {{ registry_name }}_net
driver: bridge
internal: false
EOF
templates/nginx-registry.conf.j2
cat > ~/ansible/roles/registry/templates/nginx-registry.conf.j2 << 'EOF'
{# Nginx config for Docker Registry #}
{# Managed by Ansible โ DO NOT EDIT! #}
user nginx;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 512;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/registry_access.log;
error_log /var/log/nginx/registry_error.log warn;
# โโ Large image uploads โโโโโโโโโโโโโโโโโโโ
client_max_body_size 0; # โ no limit ฮณฮนฮฑ images!
chunked_transfer_encoding on;
server {
listen 443 ssl;
server_name {{ registry_hostname }};
# โโ SSL โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ssl_certificate /etc/nginx/certs/registry.crt;
ssl_certificate_key /etc/nginx/certs/registry.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# โโ Security headers โโโโโโโโโโโโโโโโโโ
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
# โโ Registry proxy โโโโโโโโโโโโโโโโโโโโ
location /v2/ {
# โโ Auth check โโโโโโโโโโโโโโโโโโโโ
{% if registry_auth_enabled %}
auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/certs/../../../auth/htpasswd;
{% endif %}
# โโ Proxy settings โโโโโโโโโโโโโโโโ
proxy_pass http://registry:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# โโ Timeouts ฮณฮนฮฑ ฮผฮตฮณฮฌฮปฮฑ images โโโโ
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
# โโ Buffer settings โโโโโโโโโโโโโโโ
proxy_buffering off;
proxy_request_buffering off;
}
# โโ Health check โโโโโโโโโโโโโโโโโโโโโโ
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
# โโ HTTP โ HTTPS redirect โโโโโโโโโโโโโโโโโ
server {
listen 80;
server_name {{ registry_hostname }};
return 301 https://$host$request_uri;
}
}
EOF
tasks/verify.yml
cat > ~/ansible/roles/registry/tasks/verify.yml << 'EOF'
---
# ============================================================
# Registry Verification
# ============================================================
# โโ Basic connectivity โโโโโโโโโโโโโโโโโโโโโโโโ
- name: Check registry API (internal)
ansible.builtin.uri:
url: "http://localhost:5000/v2/"
status_code: [200, 401]
validate_certs: false
register: reg_api_check
ignore_errors: true
- name: Check registry API (external SSL)
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/"
status_code: [200, 401]
validate_certs: false
register: reg_ssl_check
ignore_errors: true
# โโ Authenticated check โโโโโโโโโโโโโโโโโโโโโโโ
- name: Check registry ฮผฮต credentials
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/"
status_code: 200
validate_certs: false
url_username: "{{ registry_users[0].username }}"
url_password: "{{ registry_users[0].password }}"
force_basic_auth: true
register: reg_auth_check
when: registry_users | length > 0
no_log: true
ignore_errors: true
# โโ Test push & pull โโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Login ฯฯฮฟ private registry
community.docker.docker_login:
registry_url: "https://{{ registry_hostname }}:{{ registry_ext_port }}"
username: "{{ registry_users[0].username }}"
password: "{{ registry_users[0].password }}"
tls_verify: false
no_log: true
when: registry_users | length > 0
register: login_result
- name: Pull test image
community.docker.docker_image:
name: alpine
tag: "3.19"
source: pull
when: login_result is not failed
- name: Tag ฮณฮนฮฑ private registry
community.docker.docker_image:
name: "alpine:3.19"
repository: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: local
when: login_result is not failed
- name: Push test image ฯฯฮฟ registry
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: local
push: true
tls_verify: false
when: login_result is not failed
register: push_test
- name: Delete local test image
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
state: absent
force_absent: true
when: login_result is not failed
- name: Pull test image ฮฑฯฯ registry
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: pull
tls_verify: false
when: login_result is not failed
register: pull_test
- name: Logout
community.docker.docker_login:
registry_url: "https://{{ registry_hostname }}:{{ registry_ext_port }}"
username: "{{ registry_users[0].username }}"
state: absent
no_log: true
when: registry_users | length > 0
# โโ List catalog โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Get registry catalog
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/_catalog"
status_code: 200
validate_certs: false
url_username: "{{ registry_users[0].username }}"
url_password: "{{ registry_users[0].password }}"
force_basic_auth: true
register: catalog
when: registry_users | length > 0
no_log: true
ignore_errors: true
# โโ Report โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- name: Registry Verification Report
ansible.builtin.debug:
msg:
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- "โ REGISTRY VERIFICATION โ"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ Host : {{ registry_hostname }}"
- "โ Port : {{ registry_ext_port }}"
- "โ SSL : {{ 'โ
Enabled' if registry_ssl_enabled else 'โ Disabled' }}"
- "โ Auth : {{ 'โ
Enabled' if registry_auth_enabled else 'โ Disabled' }}"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ CHECKS: โ"
- "โ API : {{ 'โ
OK' if not reg_api_check.failed else 'โ Failed' }}"
- "โ SSL : {{ 'โ
OK' if not reg_ssl_check.failed else 'โ Failed' }}"
- "โ Auth : {{ 'โ
OK' if not reg_auth_check.failed else 'โ N/A' }}"
- "โ Push : {{ 'โ
OK' if not push_test.failed else 'โ Failed' }}"
- "โ Pull : {{ 'โ
OK' if not pull_test.failed else 'โ Failed' }}"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ Catalog: {{ catalog.json.repositories | default([]) | join(', ') | default('empty') }}"
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
EOF
handlers/main.yml
cat > ~/ansible/roles/registry/handlers/main.yml << 'EOF'
---
- name: Restart registry
ansible.builtin.command:
cmd: >
docker compose
-f {{ registry_base_dir }}/docker-compose.yml
-p {{ registry_name }}
restart registry
ignore_errors: "{{ ansible_check_mode }}"
- name: Reload nginx
ansible.builtin.command:
cmd: >
docker compose
-f {{ registry_base_dir }}/docker-compose.yml
-p {{ registry_name }}
exec -T nginx nginx -s reload
ignore_errors: "{{ ansible_check_mode }}"
EOF
Vault Variables ฮณฮนฮฑ Registry
cat > /tmp/registry_vault.yml << 'EOF'
---
vault_registry_http_secret: "RegistrySecret@2026#SuperLong!"
vault_registry_admin_pass: "AdminPass@2026!"
vault_registry_user_pass: "UserPass@2026!"
EOF
# ฮ ฯฮฟฯฮธฮฎฮบฮท ฯฯฮฟ ฯ
ฯฮฌฯฯฮฟฮฝ vault
ansible-vault edit \
~/ansible/inventory/group_vars/all/vault.yml
# โ ฮ ฯฯฯฮธฮตฯฮต ฯฮฑ ฯฮฑฯฮฑฯฮฌฮฝฯ
Deployment Playbook
cat > ~/ansible/playbooks/private-registry.yml << 'EOF'
---
# ============================================================
# Private Docker Registry Deployment
# ============================================================
- name: Deploy Private Docker Registry
hosts: "{{ target | default('all_managed') }}"
become: true
gather_facts: true
pre_tasks:
- name: Registry deployment info
ansible.builtin.debug:
msg:
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- "Private Docker Registry Deployment"
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- "Host: {{ inventory_hostname }}"
- "IP : {{ ansible_facts['default_ipv4']['address'] }}"
- "Port: {{ registry_ext_port | default(443) }}"
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
tags: always
- name: Open firewall port (Debian/ferm)
ansible.builtin.lineinfile:
path: /etc/ferm/ferm.conf
regexp: ".*{{ registry_ext_port | default(443) }}.*"
line: " proto tcp dport {{ registry_ext_port | default(443) }} ACCEPT;"
insertafter: "chain INPUT"
when:
- ansible_facts['os_family'] == "Debian"
notify: Restart ferm
ignore_errors: true
roles:
- role: registry
vars:
registry_hostname: "{{ inventory_hostname }}"
registry_ext_port: 443
registry_auth_enabled: true
registry_users:
- username: admin
password: "{{ vault_registry_admin_pass }}"
- username: deploy
password: "{{ vault_registry_user_pass }}"
registry_ssl_self_signed: true
registry_gc_enabled: true
tags: registry
post_tasks:
- name: Registry Access Info
ansible.builtin.debug:
msg:
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
- "โ REGISTRY DEPLOYMENT COMPLETE! ๐ โ"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ Registry URL: โ"
- "โ {{ inventory_hostname }}:443"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ Usage: โ"
- "โ docker login {{ inventory_hostname }}"
- "โ docker tag myapp:1.0 {{ inventory_hostname }}/myapp:1.0"
- "โ docker push {{ inventory_hostname }}/myapp:1.0"
- "โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ"
- "โ Note: Self-signed cert โ add to โ"
- "โ /etc/docker/certs.d/ on clients! โ"
- "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
tags: always
handlers:
- name: Restart ferm
ansible.builtin.service:
name: ferm
state: restarted
when: ansible_facts['os_family'] == "Debian"
ignore_errors: "{{ ansible_check_mode }}"
EOF
ฮฮบฯฮญฮปฮตฯฮท
# โโ Syntax check โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ansible-playbook playbooks/private-registry.yml \
--syntax-check
# โโ Dry run โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ansible-playbook playbooks/private-registry.yml \
--check \
--limit nextcloud
# โโ Full deployment โโโโโโโโโโโโโโโโโโโโโโโโโโโ
ansible-playbook playbooks/private-registry.yml \
--limit nextcloud \
-v
# โโ ฮฯฮฝฮฟ setup โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ansible-playbook playbooks/private-registry.yml \
--tags setup \
--limit nextcloud
# โโ ฮฯฮฝฮฟ verify โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ansible-playbook playbooks/private-registry.yml \
--tags verify \
--limit nextcloud
Client Configuration
# ฮฃฮต ฮบฮฌฮธฮต Docker client ฯฮฟฯ
ฯฯฮทฯฮนฮผฮฟฯฮฟฮนฮตฮฏ ฯฮฟ registry:
# โโ Copy certificate โโโโโโโโโโโโโโโโโโโโโโโโโโ
sudo mkdir -p /etc/docker/certs.d/nextcloud:443
sudo scp ansible@nextcloud:/opt/registry/certs/registry.crt \
/etc/docker/certs.d/nextcloud:443/ca.crt
# โโ Login โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
docker login nextcloud:443
# Username: admin
# Password: ***
# โโ Push โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
docker tag nginx:alpine nextcloud:443/nginx:alpine
docker push nextcloud:443/nginx:alpine
# โโ Pull โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
docker pull nextcloud:443/nginx:alpine
ฮฃฯฮฝฮฟฯฮท D5.3
Private Registry ฮผฮต Ansible
โโโ Components:
โ โโโ registry:2 โ image storage (internal)
โ โโโ nginx โ SSL proxy (external :443)
โ
โโโ Security:
โ โโโ SSL: self-signed certificate
โ โโโ Auth: htpasswd (bcrypt)
โ โโโ Internal network (registry_net)
โ
โโโ Setup:
โ โโโ Directories: data, auth, certs, logs
โ โโโ SSL cert: openssl req -newkey rsa:4096
โ โโโ htpasswd: htpasswd -Bbc
โ
โโโ Features:
โ โโโ Garbage collection (cron)
โ โโโ Storage delete enabled
โ โโโ Pull-through cache ready
โ
โโโ Client:
โโโ Copy cert โ /etc/docker/certs.d/
โโโ docker login
โโโ docker push/pull