Image Build

Image Build #

Ansible bukan hanya untuk menjalankan container — ia juga bisa mengotomasi proses membangun image. Mengintegrasikan build image ke dalam playbook memungkinkan kamu mengontrol seluruh lifecycle: dari persiapan kode, build image, push ke registry, hingga deployment ke server production, semuanya dalam satu alur yang terdokumentasi. Artikel ini membahas bagaimana mengotomasi proses build Docker image menggunakan Ansible.

Build Image dengan docker_image #

Module community.docker.docker_image mendukung build image dari Dockerfile:

- name: Build Docker image aplikasi
  community.docker.docker_image:
    name: registry.company.com/myapp
    tag: "{{ app_version }}"
    source: build
    build:
      path: /opt/app/src        # Direktori yang berisi Dockerfile
      dockerfile: Dockerfile    # Default, bisa dikustomisasi
      args:
        APP_VERSION: "{{ app_version }}"
        BUILD_DATE: "{{ ansible_date_time.iso8601 }}"
      pull: true                # Pull base image terbaru sebelum build
      nocache: false            # Gunakan build cache jika tersedia
    state: present
  register: build_result

- name: Tampilkan image ID yang dihasilkan
  debug:
    msg: "Image berhasil dibangun: {{ build_result.image.Id }}"

Push Image ke Registry #

Setelah build, push image ke registry agar bisa digunakan di server lain:

- name: Login ke private registry
  community.docker.docker_login:
    registry_url: registry.company.com
    username: "{{ registry_username }}"
    password: "{{ registry_password }}"
  no_log: true

- name: Push image ke registry
  community.docker.docker_image:
    name: registry.company.com/myapp
    tag: "{{ app_version }}"
    push: true
    source: local             # Gunakan image yang sudah ada di local

- name: Tag image sebagai latest
  community.docker.docker_image:
    name: registry.company.com/myapp
    repository: registry.company.com/myapp
    tag: latest
    source: local
    force_tag: true

- name: Push tag latest
  community.docker.docker_image:
    name: registry.company.com/myapp
    tag: latest
    push: true
    source: local

- name: Logout dari registry
  community.docker.docker_login:
    registry_url: registry.company.com
    state: absent

Strategi Tagging yang Baik #

Tag yang baik mengidentifikasi image secara unik dan tidak ambigu:

# vars untuk build
app_version: "2.1.0"
git_commit: "{{ lookup('pipe', 'git rev-parse --short HEAD') }}"
build_date: "{{ ansible_date_time.date }}"

# Tag yang dihasilkan:
image_tags:
  - "{{ app_version }}"                              # 2.1.0
  - "{{ app_version }}-{{ git_commit }}"             # 2.1.0-a3f5c1d
  - "{{ app_version }}-{{ build_date }}"             # 2.1.0-2024-03-15
  - latest                                           # Hanya untuk branch main
- name: Build dan tag image dengan semua tag
  community.docker.docker_image:
    name: registry.company.com/myapp
    tag: "{{ item }}"
    source: "{{ 'build' if loop.index == 1 else 'local' }}"
    build:
      path: /opt/app/src
    push: true
  loop: "{{ image_tags }}"
  loop_control:
    label: "registry.company.com/myapp:{{ item }}"
Tag latest sering disalahgunakan. Di production, selalu deploy dengan tag versi yang spesifik (2.1.0 atau 2.1.0-a3f5c1d) — bukan latest. Tag latest tidak menjamin kamu tahu persis versi apa yang berjalan, dan tidak bisa di-rollback dengan mudah.

Build Pipeline Lengkap #

Menggabungkan semua langkah menjadi satu playbook pipeline:

# playbooks/build-and-push.yml
---
- name: Build dan push Docker image
  hosts: localhost       # Build di control node atau build server
  vars:
    registry: registry.company.com
    image_name: myapp
    app_version: "{{ version | mandatory }}"   # Harus dipass via -e version=x.y.z

  tasks:
    - name: Validasi versi yang diberikan
      assert:
        that:
          - app_version is defined
          - app_version is match('^[0-9]+\.[0-9]+\.[0-9]+$')
        fail_msg: "Gunakan -e version=x.y.z (contoh: -e version=2.1.0)"

    - name: Checkout kode versi {{ app_version }}
      git:
        repo: https://github.com/company/myapp.git
        dest: /tmp/myapp-build
        version: "v{{ app_version }}"
        force: true

    - name: Build image
      community.docker.docker_image:
        name: "{{ registry }}/{{ image_name }}"
        tag: "{{ app_version }}"
        source: build
        build:
          path: /tmp/myapp-build
          pull: true
        state: present

    - name: Login ke registry
      community.docker.docker_login:
        registry_url: "{{ registry }}"
        username: "{{ registry_username }}"
        password: "{{ registry_password }}"
      no_log: true

    - name: Push image
      community.docker.docker_image:
        name: "{{ registry }}/{{ image_name }}"
        tag: "{{ app_version }}"
        push: true
        source: local

    - name: Logout dari registry
      community.docker.docker_login:
        registry_url: "{{ registry }}"
        state: absent

    - name: Cleanup direktori build
      file:
        path: /tmp/myapp-build
        state: absent
# Jalankan pipeline build
ansible-playbook playbooks/build-and-push.yml -e version=2.1.0

Membersihkan Image Lama #

Image yang tidak lagi digunakan akan memenuhi disk. Bersihkan secara berkala:

- name: Hapus image lama yang tidak digunakan
  community.docker.docker_prune:
    images: true
    images_filters:
      dangling: true          # Hapus hanya dangling images (untagged)
    timeout: 300

- name: Hapus semua image yang tidak digunakan (lebih agresif)
  community.docker.docker_prune:
    images: true
    images_filters:
      until: "168h"           # Hapus image yang tidak digunakan lebih dari 7 hari

Ringkasan #

  • Module docker_image dengan source: build untuk membangun image dari Dockerfile — mendukung build args, cache control, dan pull base image.
  • Selalu login ke registry sebelum push dan logout setelah selesai — gunakan no_log: true untuk menyembunyikan credential.
  • Strategi tag yang baik menggunakan versi + git commit untuk traceability penuh — selalu tahu kode mana yang ada di image mana.
  • Jangan deploy dengan tag latest di production — gunakan tag versi spesifik untuk reproducibility dan kemampuan rollback.
  • Buat playbook build pipeline yang menerima versi via -e version=x.y.z — proses build yang konsisten dan dapat diulang.
  • Bersihkan image lama secara berkala dengan docker_prune — image yang menumpuk bisa menghabiskan disk dalam waktu singkat.

← Sebelumnya: Ansible vs Docker Compose   Berikutnya: Apa itu Kubernetes? →

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