Deploy Container

Deploy Container #

Setelah host Docker siap, saatnya menjalankan container. Ansible menyediakan module community.docker yang memungkinkan kamu mendeploy, mengkonfigurasi, dan mengelola container dengan cara yang sama persis seperti kamu mengelola konfigurasi sistem — deklaratif dan idempoten. Artikel ini membahas pola deployment container yang umum digunakan dan bagaimana Ansible mengelolanya.

Persiapan: Instal Collection #

Module Docker tidak termasuk dalam Ansible Core dan perlu diinstal terlebih dahulu:

ansible-galaxy collection install community.docker
pip install docker    # Library Python yang diperlukan oleh module

Menjalankan Container Sederhana #

Module community.docker.docker_container adalah module utama untuk mengelola lifecycle container:

- name: Jalankan container nginx
  community.docker.docker_container:
    name: nginx-web
    image: nginx:1.24-alpine
    state: started
    restart_policy: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /opt/nginx/conf:/etc/nginx/conf.d:ro
      - /opt/nginx/ssl:/etc/ssl/nginx:ro
      - nginx-logs:/var/log/nginx
    env:
      TZ: "Asia/Jakarta"

State yang tersedia:

state: started   → Jalankan container jika belum berjalan
state: stopped   → Hentikan container
state: absent    → Hentikan dan hapus container
state: present   → Buat container tapi tidak langsung jalankan

Mengelola Image #

Sebelum menjalankan container, pastikan image yang diperlukan sudah ada di host:

- name: Pull image terbaru sebelum deployment
  community.docker.docker_image:
    name: "{{ app_image }}"
    tag: "{{ app_version }}"
    source: pull
    force_source: true    # Pull meski tag sudah ada (untuk :latest atau tag mutable)

- name: Pull image dari private registry
  community.docker.docker_image:
    name: registry.company.com/myapp
    tag: "{{ app_version }}"
    source: pull
    force_source: false   # Jangan pull ulang jika sudah ada (untuk tag immutable)
# Login ke private registry terlebih dahulu
- name: Login ke private Docker registry
  community.docker.docker_login:
    registry_url: registry.company.com
    username: "{{ registry_username }}"
    password: "{{ registry_password }}"
  no_log: true

Pola Deployment: Stop, Deploy, Start #

Untuk deployment aplikasi yang sudah berjalan, ikuti pola yang aman:

- name: Deploy aplikasi v{{ app_version }}
  hosts: appservers
  vars:
    app_image: registry.company.com/myapp
    app_container_name: myapp
  
  tasks:
    - name: Pull image versi baru
      community.docker.docker_image:
        name: "{{ app_image }}"
        tag: "{{ app_version }}"
        source: pull

    - name: Stop container lama
      community.docker.docker_container:
        name: "{{ app_container_name }}"
        state: stopped
      ignore_errors: true   # Tidak apa-apa jika container belum ada

    - name: Hapus container lama
      community.docker.docker_container:
        name: "{{ app_container_name }}"
        state: absent

    - name: Jalankan container baru
      community.docker.docker_container:
        name: "{{ app_container_name }}"
        image: "{{ app_image }}:{{ app_version }}"
        state: started
        restart_policy: unless-stopped
        ports:
          - "{{ app_port }}:8080"
        env:
          DATABASE_URL: "{{ db_url }}"
          REDIS_URL: "{{ redis_url }}"
          APP_ENV: "{{ env }}"
        volumes:
          - "{{ app_data_dir }}:/app/data"
        networks:
          - name: app-network

    - name: Tunggu container siap
      uri:
        url: "http://localhost:{{ app_port }}/health"
        status_code: 200
      register: health_check
      until: health_check.status == 200
      retries: 12
      delay: 5

Mengelola Docker Network #

- name: Buat network untuk aplikasi
  community.docker.docker_network:
    name: app-network
    driver: bridge
    ipam_config:
      - subnet: "172.20.0.0/16"
        gateway: "172.20.0.1"
    state: present

- name: Buat network untuk database (isolated)
  community.docker.docker_network:
    name: db-network
    driver: bridge
    internal: true    # Network internal, tidak bisa akses internet
    state: present

Mengelola Docker Volume #

- name: Buat volume untuk data persistent
  community.docker.docker_volume:
    name: "{{ item }}"
    state: present
  loop:
    - app-data
    - db-data
    - redis-data

- name: Jalankan database dengan volume persistent
  community.docker.docker_container:
    name: postgres
    image: postgres:15-alpine
    state: started
    restart_policy: unless-stopped
    volumes:
      - db-data:/var/lib/postgresql/data
    env:
      POSTGRES_DB: "{{ db_name }}"
      POSTGRES_USER: "{{ db_user }}"
      POSTGRES_PASSWORD: "{{ db_password }}"
    networks:
      - name: db-network
    no_log: true

Cek Status Container #

- name: Kumpulkan informasi semua container yang berjalan
  community.docker.docker_container_info:
    name: myapp
  register: container_info

- name: Tampilkan status container
  debug:
    msg:
      - "Container: {{ container_info.container.Name }}"
      - "Status: {{ container_info.container.State.Status }}"
      - "Image: {{ container_info.container.Config.Image }}"
      - "Started: {{ container_info.container.State.StartedAt }}"
  when: container_info.exists

Ringkasan #

  • Instal community.docker collection dan library docker Python sebelum menggunakan module Docker.
  • docker_container adalah module utama — deklaratif dan idempoten, sama seperti module Ansible lainnya.
  • Selalu pull image sebelum deployment dan gunakan tag yang immutable (bukan latest) untuk reproducibility.
  • Pola deployment yang aman: pull → stop → remove → run — memastikan container baru berjalan dengan image yang benar.
  • restart_policy: unless-stopped untuk container production — container otomatis restart setelah reboot host atau crash.
  • Gunakan networks untuk isolasi — container yang tidak perlu berkomunikasi sebaiknya tidak berada di network yang sama.
  • no_log: true untuk task yang melibatkan environment variable sensitif seperti password database.

← Sebelumnya: Provision Host   Berikutnya: Ansible vs Docker Compose →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact