app.yml
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env ansible-playbook
---
#==============================================================#
# File : app.yml
# Desc : copy and launch docker compose app
# Ctime : 2025-01-11
# Mtime : 2026-07-10
# Path : app.yml
# Docs : https://pigsty.io/docs/app
# License : Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright : 2018-2026 Ruohang Feng / Vonng (rh@vonng.com)
#==============================================================#
#--------------------------------------------------------------#
# Usage
#--------------------------------------------------------------#
# 1. specify the `app` param
# by default, it's a docker compose app in the app/ folder
# configure it in the pigsty.yml or pass it as `-e app=<name>`
#
# 2. OPTIONAL, specify app details with apps:
#
# This playbook relies on the DOCKER module to work
# This playbook will:
# 1. copy docker compose resource from app/<appname> to /opt/<appname>
# 2. create required dirs with app.file (optional)
# 3. overwrite .env config with app.conf (optional)
# 4. launch app with docker compose up
#
#--------------------------------------------------------------#
# Example
#--------------------------------------------------------------#
# ./app.yml -e app=pgweb # simple app can be launched directly
# ./app.yml -e app=pgadmin # without any further configuration
#
# ./app.yml -e app=bytebase # for sophisticated software
# ./app.yml -e app=odoo # configure pigsty.yml `apps`
# ./app.yml -e app=dify # to have fine-grained control
#--------------------------------------------------------------#
- name: NODE ID
become: true
hosts: all
gather_facts: no
roles:
- { role: node_id ,tags: id }
#- { role: docker ,tags: docker }
# Run docker compose application (require the docker module)
- name: APP INSTALL
hosts: all
gather_facts: no
become: true
tasks:
#----------------------------------------------------------#
# Validate app and app definition [preflight]
#----------------------------------------------------------#
- name: preflight
tags: [ app_check, preflight, always ]
connection: local
block:
- name: validate app parameter
assert:
that:
- app is defined
- app != ''
fail_msg: "the 'app' arg is not given (-e app=<name>)"
- name: validate docker exists
assert:
that:
- docker_enabled is defined and docker_enabled
fail_msg: "docker_enabled is required to install app"
- name: fetch app definition
no_log: true
set_fact:
app_def: "{{ apps[app] | default({}) }}"
- name: set app properties
no_log: true
set_fact:
app_name: "{{ app }}"
app_src: "{{ app_def.src | default(playbook_dir + '/app/' + app) }}" # override src name with app.src
app_dest: "{{ app_def.dest | default('/opt/' + app) }}" # override dest name with app.dest
app_conf: "{{ app_def.conf | default({}) }}" # application configuration
app_file: "{{ app_def.file | default([]) }}" # application files & directories
app_args: "{{ app_def.args | default('') }}" # application makefile shortcuts
- name: print app details
debug:
msg: "app: {{ app_name }}, src: {{ app_src }}, dest: {{ app_dest }}, conf keys: {{ app_conf.keys() | list }}, file: {{ app_file }}"
#----------------------------------------------------------#
# Install app resources to /opt [app_install]
#----------------------------------------------------------#
# copy docker app folder to /opt/<app.dest> or /opt/<app.name>
# this will fail if the app/<appname> folder does not exist
- name: install app resource to /opt
tags: app_install
copy: src="{{ app_src }}/" dest="/{{ app_dest }}/"
#----------------------------------------------------------#
# Prepare files & directories [app_file]
#----------------------------------------------------------#
- name: setup app files & directories
tags: app_file
when: app_file | length > 0
file: "{{ item }}"
with_items: "{{ app_file }}"
#----------------------------------------------------------#
# Configure app with .env [app_config]
#----------------------------------------------------------#
# write runtime overrides without exposing values; protect the file when secrets are materialized
- name: configure app by updating .env
tags: app_config
when: app_conf | length > 0
no_log: true
vars:
app_env_value: "{{ '' if item.value is none else (item.value | string | lower if item.value is boolean else item.value | string) }}"
lineinfile:
path: "{{ app_dest }}/.env"
regexp: '^{{ item.key | upper }}='
# apps.*.conf contains literal values, not dotenv expressions. Quote
# whitespace/comments/quotes and escape dollars before Compose parses it.
line: >-
{{ item.key | upper }}={{ app_env_value if (app_env_value | regex_search('^[A-Za-z0-9_./:@,+=?%-]*$')) is not none else (app_env_value | replace('$', '$$') | to_json(ensure_ascii=False)) }}
create: yes
mode: '0600'
loop: "{{ app_conf | dict2items }}"
#----------------------------------------------------------#
# Launch app with make command [app_launch]
#----------------------------------------------------------#
# it may take a while to pull images, or very fast if you already have local image loaded, or proxy, mirror.
- name: launch app
tags: app_launch
# On a fresh host the destination exists only after the copy task runs;
# check mode must not try to chdir into that not-yet-created directory.
when: not ansible_check_mode
shell:
cmd: make {{ app_args }}
chdir: "{{ app_dest }}"
...