개요
- awx-ee는 AWX에서 Job을 실행할 때
ansible-playbook이 동작하는 실행 환경(Execution Environment, EE) 컨테이너 이미지다. - 컨테이너가 생성되는 방식은 AWX 설치 환경에 따라 다르다. awx-operator(쿠버네티스)로 설치했다면 Job마다 Pod가 생성되고, 도커 기반 환경이라면 AWX 내부에서 podman 컨테이너로 실행된다 (여기에서는 AWX 도커 환경에서 운영 중인 경우를 기반으로 설명한다)
- 기본 awx-ee 이미지에는 ansible-core와 자주 쓰는 컬렉션 일부만 들어 있다. 필요한 컬렉션이 없거나 다른 버전이 필요하면 직접 추가해야 한다.
- 컬렉션은 AWX 프로젝트의
collections/requirements.yml로 실행 시점에 설치할 수도 있다. 하지만 아래 경우에는 EE 이미지를 직접 만드는 편이 낫다.- 모듈이 요구하는 Python 라이브러리 또는 시스템 패키지가 필요할 때 (Job 실행 시점에서는 설치 불가능)
- 컬렉션 및 라이브러리 버전을 고정해서 실행 결과를 재현할 수 있도록 유지하고 싶을 때
- 이 글에서는 커스텀 EE 이미지를 정의하고 GitHub Actions로 빌드해 GHCR에 올린 뒤 AWX에서 사용하는 과정까지 정리한다.
전체 흐름과 프로젝트 구조
전체 흐름
execution-environment.yml에 이미지에 넣을 의존성을 정의한다.- 로컬에서
tox -e docker로 빌드해 정상 동작을 확인한다. develop브랜치를master로 PR 병합한 뒤 GitHub Release를 실행한다.- GitHub Actions가 이미지를 빌드해 GHCR(GitHub Container Registry)에 push한다.
- AWX에 GHCR 인증 정보와 실행 환경을 등록하고, 템플릿에서 해당 실행 환경을 선택한다.
프로젝트 구조
jslim-awx-ee/
├── .github/workflows/image-build.yml # 이미지 빌드, push 워크플로
├── execution-environment.yml # EE 정의 파일 (이미지 설계도)
├── requirements.txt # 빌드 도구(ansible-builder) 의존성
├── tox.ini # 빌드 명령 정의
└── docs/ # 프로젝트 문서
ansible-builder
- podman 또는 docker로 Ansible 실행 환경 컨테이너 이미지를 만들어 주는 도구다.
- 설치:
pip install ansible-builder(이 프로젝트는3.1.1로 고정. 2026-10-02 기준 최신 버전) - 실행 예:
ansible-builder build -t jslim-awx-ee:local -f execution-environment.yml -v 3-t를 생략하면ansible-execution-env:latest태그가 붙는다.- 빌드 과정에서 현재 디렉터리에
context/빌드 컨텍스트(Containerfile 등)가 생성된다. 커밋 대상이 아니므로.gitignore에 등록한다.
- 이미지는 아래 4단계를 거쳐 만들어진다.
- base: base 이미지 위에 Python 인터프리터, ansible-core, ansible-runner를 설치한다.
- galaxy:
ansible-galaxy로 컬렉션을 설치한다. - builder: Python 패키지를 설치/빌드한다. 컴파일용 시스템 패키지(
compile)는 여기서만 사용한다. - final: 실행에 필요한 시스템 패키지, Python 패키지, 컬렉션만 모아 최종 이미지를 만든다.
execution-environment.yml
예제 파일
---
version: 3
images:
base_image:
name: quay.io/centos/centos:stream9
dependencies:
python_interpreter:
package_system: python3.13
python_path: /usr/bin/python3.13
ansible_core:
package_pip: ansible-core==2.20.1
ansible_runner:
package_pip: ansible-runner==2.4.2
galaxy: |
---
collections:
- name: ansible.posix
version: "2.1.0"
- name: ansible.utils
version: "6.0.0"
- name: community.general
version: "12.2.0"
- name: ansible.windows
version: "3.3.0"
- name: ansible.netcommon
version: "8.2.0"
- name: fortinet.fortios
version: "2.4.2"
- name: community.crypto
version: "3.1.0"
- name: awx.awx
version: "24.6.1"
- name: community.proxmox
version: "1.5.0"
- name: amazon.aws
version: "10.1.2"
- name: community.aws
version: "10.0.0"
- name: google.cloud
version: "1.10.2"
- name: community.docker
version: "5.0.4"
- name: containers.podman
version: "1.18.0"
- name: kubernetes.core
version: "6.2.0"
- name: community.mysql
version: "4.0.1"
- name: community.postgresql
version: "4.2.0"
system: |
git-core [platform:rpm]
python3.13-devel [platform:rpm compile]
libcurl-devel [platform:rpm compile]
git-lfs [platform:rpm]
sshpass [platform:rpm]
rsync [platform:rpm]
unzip [platform:rpm]
podman-remote [platform:rpm]
cmake [platform:rpm compile]
gcc [platform:rpm compile]
gcc-c++ [platform:rpm compile]
make [platform:rpm compile]
openssl-devel [platform:rpm compile]
libpq-devel [platform:rpm]
python: |
ansible-sign==0.1.4
boto3>=1.34.0
botocore>=1.34.0
cryptography>=42.0.0
docker>=7.1.0
google-auth
jsonpatch
jsonschema
kubernetes>=28.1.0
ncclient
netaddr
paramiko
proxmoxer==2.2.0
psycopg[binary]>=3.2.3
PyMySQL>=1.1.1
python-daemon
pywinrm>=0.4.3
PyYAML
pyyaml
receptorctl
requests
six
toml
xmltodict
additional_build_steps:
# [추가] 베이스 이미지 시작 직후, Python 설치 전에 EPEL 저장소를 먼저 활성화합니다.
prepend_base:
- RUN /usr/bin/dnf install -y epel-release
- RUN /usr/bin/crb enable
append_base:
- RUN $PYCMD -m pip install -U pip
append_final:
- COPY --from=quay.io/ansible/receptor:v1.4.1 /usr/bin/receptor /usr/bin/receptor
- RUN mkdir -p /var/run/receptor
- RUN git lfs install --system
# SymLink `python` -> `python3.13`
- RUN alternatives --install /usr/bin/python python /usr/bin/python3.13 313
version
- EE 정의 파일의 스키마 버전이다 (ansible-builder 버전 아님)
3을 쓰려면 ansible-builder 3.x가 필요하다.
images
base_image: 실행 환경의 부모 이미지를 지정한다.- upstream awx-ee를 참고해 CentOS Stream 9를 사용한다.
dependencies
- 최종 이미지에 설치할 의존성을 정의한다.
python_interpreter
package_system: dnf로 설치할 Python 시스템 패키지 이름python_path: 이미지에서 사용할 Python 인터프리터 경로- ansible-core 2.20은 컨트롤 노드 Python 3.12 ~ 3.14를 지원하므로, 호환성을 맞추기 위해 Python 3.13을 사용한다.
ansible_core, ansible_runner
package_pip: pip에 그대로 전달할 값이다.ansible-core: 최신 버전 설치 (버전 지정이 없다면)ansible-core==2.20.1: 특정 버전 설치 (권장)- ansible community 13.x 기준으로 셋팅
- 이전에는 ansible-core 2.14를 사용했지만 2.20으로 올렸다. 올리기 전에 관리 대상 노드의 Python 버전을 반드시 확인해야 한다.
- 자세한 사항은 Ansible 버전별 호환 관계 정리 문서를 참고
| ansible-core | 컨트롤 노드 Python | 대상 노드 Python |
|---|---|---|
| 2.14 | 3.9 ~ 3.11 | 2.7, 3.5 ~ 3.11 |
| 2.20 | 3.12 ~ 3.14 | 3.9 ~ 3.14 |
⚠️ CentOS 7(Python 2.7/3.6)이나 기본 Python이 3.6인 RHEL 8 호스트는 2.20 이미지로 관리할 수 없다. 이런 호스트에는 Python 3.9 이상을 설치하거나, 구버전 ansible-core로 만든 EE를 따로 두고 템플릿별로 골라 쓴다.
galaxy
- 설치할 Ansible 컬렉션 목록이며, 표준
requirements.yml형식을 그대로 사용한다. - 버전은 따옴표로 감싼 문자열로 적는다.
version: 2.10처럼 쓰면 YAML이 숫자2.1로 해석할 수 있다.
| 컬렉션 | 용도 |
|---|---|
| ansible.posix | ACL, mount, sysctl, firewalld 등 POSIX 시스템 관리 |
| ansible.utils | 데이터 검증 및 변환 필터 (IP 주소 필터, XML 변환, 스키마 검증 등) |
| community.general | 특정 컬렉션에 속하지 않는 다양한 범용 모듈 |
| ansible.windows | Windows 기본 관리 |
| ansible.netcommon | 네트워크 장비용 공통 연결 플러그인 (network_cli, netconf, httpapi) |
| fortinet.fortios | FortiGate(FortiOS) 방화벽 관리 |
| community.crypto | 인증서, 키 관리 (OpenSSL, ACME) |
| awx.awx | 플레이북에서 AWX API 제어 |
| community.proxmox | Proxmox VE 관리 |
| amazon.aws | AWS 리소스 관리 (핵심 모듈) |
| community.aws | AWS 리소스 관리 (확장 모듈) |
| google.cloud | GCP 리소스 관리 |
| community.docker | Docker 관리 |
| containers.podman | Podman 관리 |
| kubernetes.core | 쿠버네티스, OpenShift 리소스 관리 |
| community.mysql | MySQL, MariaDB 관리 |
| community.postgresql | PostgreSQL 관리 |
컬렉션 버전을 고를 때는 아래를 확인한다.
- 지원하는 ansible-core 버전: Galaxy 페이지의 “Requires Ansible” 항목, 또는 컬렉션의
meta/runtime.yml에 있는requires_ansible값을 확인한다. - 빌드한 뒤에는
ansible-galaxy collection list로 실제 설치된 버전을 확인한다 (아래 ‘빌드 결과 검증’ 참고).
python
- 컬렉션 모듈이 내부에서 사용하는 Python 라이브러리 목록이며,
requirements.txt형식을 그대로 사용한다. - 모듈 공식 문서의 “Requirements” 항목에 필요한 라이브러리가 적혀 있다. 컬렉션만 넣고 라이브러리를 빠뜨리면 실행 시점에
ModuleNotFoundError가 발생한다.
| 패키지 | 사용처 |
|---|---|
| boto3, botocore | amazon.aws, community.aws |
| google-auth, requests | google.cloud 등 HTTP API를 쓰는 컬렉션 |
| kubernetes, jsonpatch | kubernetes.core |
| docker | community.docker |
| proxmoxer | community.proxmox |
| PyMySQL | community.mysql |
| psycopg[binary] | community.postgresql |
| pywinrm | ansible.windows (WinRM 연결) |
| ncclient | ansible.netcommon (NETCONF) |
| paramiko | SSH 연결 (paramiko 연결 플러그인, 네트워크 장비) |
| cryptography | community.crypto |
| netaddr | ansible.utils의 IP 주소 필터 |
| jsonschema | ansible.utils의 스키마 검증 |
| xmltodict | ansible.utils의 XML 변환 필터 |
| ansible-sign | AWX 프로젝트 콘텐츠 서명 검증 |
| receptorctl | receptor 제어 도구 |
| python-daemon, six, toml, PyYAML | upstream awx-ee 구성을 따른 공통 라이브러리 |
system
- 설치할 시스템 패키지 목록이며 bindep 형식을 따른다.
[platform:rpm]: RHEL·CentOS 계열(rpm)에서만 설치한다.compile: Python 패키지를 빌드할 때만 필요한 패키지다. builder 단계에서만 쓰이고 최종 이미지에는 들어가지 않는다. gcc, make 같은 컴파일 도구에 붙여 두면 이미지 크기를 줄일 수 있다.
| 구분 | 패키지 | 용도 |
|---|---|---|
| 실행용 | git-core, git-lfs | Git 저장소에 있는 프로젝트·컬렉션 사용 |
| 실행용 | sshpass | SSH 비밀번호 인증 |
| 실행용 | rsync, unzip | synchronize, unarchive 모듈 |
| 실행용 | podman-remote | 원격 Podman 서비스에 접속하는 클라이언트 |
| 실행용 | libpq-devel | PostgreSQL 클라이언트 라이브러리(libpq) |
빌드용 (compile) |
python3.13-devel, libcurl-devel, openssl-devel, gcc, gcc-c++, make, cmake | Python 패키지의 C 확장 컴파일 |
additional_build_steps
빌드 단계 앞뒤에 Containerfile 명령을 직접 넣을 때 쓴다. 단계마다 prepend_*(시작 직후)와 append_*(끝나기 직전)가 있다.
“ansible-builder” 단락에서 이미지 생성 과정을 참고하면 아래의 표를 이해하기 쉽다.
| 키 | 실행 시점 | 이 프로젝트에서 하는 일 |
|---|---|---|
prepend_base |
base 단계 시작 직후, Python 설치 전 | EPEL 설치와 CRB 저장소 활성화 |
append_base |
base 단계 마지막 | pip 업그레이드 |
append_final |
final 단계 마지막 | receptor 복사, git-lfs 설정, python 심볼릭 링크 |
$PYCMD:python_path로 지정한 인터프리터(/usr/bin/python3.13)를 가리킨다.- EPEL과 CRB
crb명령은 EL9용epel-release패키지에 들어 있으므로 반드시epel-release를 먼저 설치한다.system목록이 아니라prepend_base에 둔 이유는 아래 ‘트러블슈팅’에서 설명한다.
- receptor
- awx-ee 기본 버전과 마찬가지로 receptor 바이너리를 이미지에 복사한다.
- awx-operator 환경에서는 awx-ee 이미지가 컨트롤 플레인에서 receptor를 실행하는 용도로도 쓰여 기본 이미지에 포함되어 있다. 작업 실행 전용 EE라면 필수는 아니지만, 원본과 구성을 맞추기 위해 유지한다.
devel태그는 변경이 잦기 때문에 빌드 결과를 재현할 수 없으므로v1.4.1로 고정했다.
git lfs install --system: 시스템 전역에 Git LFS를 설정한다.alternatives ...:python명령이python3.13을 가리키도록 한다.
로컬 빌드와 검증
GitHub Actions에 올리기 전에 로컬에서 먼저 빌드해 본다. CI에서도 같은 tox 명령을 쓰므로 로컬에서 성공하면 CI에서도 같은 결과를 기대할 수 있다.
requirements.txt
ansible-builder==3.1.1
- 이미지 안에 설치되는 패키지가 아니라, 이미지를 만드는 도구의 의존성이다.
- 이미지 안에 들어갈 Python 패키지는
execution-environment.yml의python에 적는다.
tox.ini
[tox]
minversion = 1.6
skipsdist = True
[testenv]
basepython = python3
install_command = pip install {opts} {packages}
deps = -r{toxinidir}/requirements.txt
[testenv:docker]
passenv = HOME,DOCKER_BUILDKIT
allowlist_externals =
/bin/bash
docker
commands =
ansible-builder build -v3 {posargs} --container-runtime=docker
- tox는 가상 환경을 만들고 그 안에서 정해진 명령을 실행한다. 여기서는 빌드 명령을 로컬과 CI에서 똑같이 맞추는 용도로 쓴다.
skipsdist = True: 이 프로젝트는 Python 패키지가 아니므로 패키징 단계를 건너뛴다.deps:requirements.txt의 ansible-builder를 가상 환경에 설치한다.[testenv:docker]:tox -e docker로 실행할 환경이다.passenv: 가상 환경 안으로 전달할 환경 변수 (BuildKit 사용 여부 등)allowlist_externals: 가상 환경 밖의 명령(docker) 실행 허용{posargs}:tox -e docker -- <인자>에서--뒤의 인자가 이 자리에 들어간다.--container-runtime=docker: ansible-builder 기본값은 podman이므로 docker를 명시한다.
빌드
pip install tox
tox -e docker -- --tag=jslim-awx-ee:local
빌드 결과 검증
# ansible-core, Python 버전 확인
docker run --rm jslim-awx-ee:local ansible --version
# 설치된 컬렉션과 버전 확인
docker run --rm jslim-awx-ee:local ansible-galaxy collection list
# 설치된 Python 패키지 확인
docker run --rm jslim-awx-ee:local python -m pip list
GHCR 토큰 준비
워크플로가 GHCR에 이미지를 push하려면 토큰이 필요하다. 워크플로를 처음 실행하기 전에 준비한다.
토큰 생성
- GitHub 프로필 → Settings → Developer settings → Personal access tokens → Tokens (classic)
- GitHub Packages는 classic 토큰만 지원한다. fine-grained 토큰으로는 인증할 수 없다.
- 권한(scope)은
write:packages를 선택한다(이미지 pull 권한 포함). - 만료일을 지정했다면 만료 전에 갱신해야 한다. 만료되면 워크플로의 로그인 단계가 실패한다.
Secrets 등록
- 레포지토리 → Settings → Security and quality → Secrets and variables → Actions → New repository secret
- 이름:
GHCR_TOKEN, 값: 앞에서 만든 토큰
(선택) GITHUB_TOKEN으로 대신하기 - secrets 등록 대체
같은 레포지토리에 연결된 패키지라면 개인 토큰 없이 워크플로가 자동으로 발급하는 GITHUB_TOKEN으로도 push할 수 있다. 토큰 만료를 관리할 필요가 없어진다.
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Login to GitHub Container Registry
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
GitHub Actions 워크플로
image-build.yml
name: Docker Image CI with GHCR
on:
# 1. 정식 배포: GitHub UI에서 Release를 생성(Publish)했을 때 실행
release:
types:
- published
workflow_dispatch:
inputs:
test_tag:
description: 'Test Tag (e.g., test-v1)'
required: false
default: 'devel'
env:
DOCKER_IMAGE: ghcr.io/${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Login to GitHub Container Registry
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Set Tag Name
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
# Release 이벤트인 경우 태그 이름 사용 (예: v1.0.0)
echo "TAG_NAME=${{ github.ref_name }}" >> $GITHUB_ENV
echo "IS_RELEASE=true" >> $GITHUB_ENV
else
# 수동 실행인 경우 입력받은 태그 사용
echo "TAG_NAME=${{ inputs.test_tag }}" >> $GITHUB_ENV
echo "IS_RELEASE=false" >> $GITHUB_ENV
fi
- name: Build and Push image
env:
DOCKER_BUILDKIT: 1
run: |
FULL_IMAGE_NAME="${{ env.DOCKER_IMAGE }}:${{ env.TAG_NAME }}"
# 1. 해당 태그(버전)로 빌드
tox -e docker -- --tag=$FULL_IMAGE_NAME
# 2. 해당 태그(버전) 푸시
docker push $FULL_IMAGE_NAME
트리거 (on)
- release: GitHub에서 Release를 발행했을 때 (정식 배포). 태그는 Release 태그 이름 (예:
1.0.0)을 사용 - workflow_dispatch: Actions 탭에서 직접 실행했을 때 (테스트). 태그는 입력한
test_tag(기본값devel)을 사용 - 브랜치 push로는 빌드하지 않는다. 커밋할 때마다 이미지를 만들지 않고, 정식 이미지 태그는 Release로만 만들도록 통제하기 위해서다.
env
DOCKER_IMAGE: 태그를 뺀 이미지 이름이다. 태그는 빌드 단계에서 붙인다.github.repository는소유자/레포지토리형식이므로 이미지 이름은ghcr.io/susoterran/jslim-awx-ee가 된다.
⚠️ 이미지 이름에는 대문자를 쓸 수 없다. 사용자명이나 레포지토리 이름에 대문자가 있으면 소문자로 바꿔야 한다.
runs-on
ubuntu-latest: GitHub가 제공하는 최신 Ubuntu 러너를 쓴다.- 특정 버전 러너를 지정하려면 지원 여부를 꼭 확인해야 한다. 지원하지 않는 러너를 지정하면 Job이
Queued상태에서 넘어가지 않는다. - 러너를 직접 구성해 쓸 수도 있다(self-hosted runner).
steps
1. Checkout repository
- 워크플로를 실행시킨 ref의 소스를 가져온다. 기본 브랜치를 가져오는 것이 아니다.
- release 이벤트: Release 태그가 가리키는 커밋
- workflow_dispatch: 실행할 때 고른 브랜치
2. Install Python
- 러너에 Python 3.9를 설치하고 PATH에 추가한다.
- 이 Python은 tox와 ansible-builder를 실행하는 용도일 뿐이다. 이미지 안의 Python(3.13)과는 관계없다.
3. Install dependencies
- pip를 최신화하고 tox를 설치한다. ansible-builder는 tox가 가상 환경에 설치한다.
4. Login to GitHub Container Registry
- GHCR에 로그인한다.
github.actor: 워크플로를 실행한 사용자 (github 컨텍스트)secrets.GHCR_TOKEN: 앞에서 등록한 토큰
5. Set Tag Name
- 이벤트 종류에 따라 이미지 태그를 정해
GITHUB_ENV에TAG_NAME으로 저장한다. 이후 단계에서env.TAG_NAME으로 읽는다. - release 이벤트의
github.ref_name은 Release 태그 이름이다.
6. Build and Push image
DOCKER_BUILDKIT=1: BuildKit으로 빌드한다(tox의passenv로 전달된다).tox -e docker -- --tag=...: 로컬 빌드와 같은 명령에 이미지 태그만 넘긴다.- 빌드한 이미지를 GHCR에 push한다.
이미지 배포
정식 배포 (Release)
develop브랜치를master로 PR 병합한다.- 레포지토리 메인 화면의 Releases → Draft a new release
- Choose a tag에 새 버전(예:
1.0.0)을 입력하고, Target은master를 선택한다. - 제목과 변경 내용을 작성한다.
- Publish release를 누르면 Actions 탭에서 워크플로가 실행된다.
- 빌드가 성공하면 레포지토리 메인 화면 오른쪽 Packages에 해당 태그의 이미지가 나타난다.
⚠️ Release 태그 이름이 그대로 이미지 태그가 된다.
v1.0.0으로 만들면 이미지 태그도v1.0.0이다.
테스트 빌드 (수동 실행)
- Actions 탭 → Docker Image CI with GHCR 선택
- Run workflow → 빌드할 브랜치 선택 (
devel) - Run workflow를 눌러 실행한다.
AWX에서 실행 환경 사용하기
인증 정보 생성
GHCR에 처음 올린 패키지는 기본적으로 private이므로, AWX가 이미지를 받으려면 인증 정보가 필요하다.
- 리소스 → 인증 정보 → 추가
- 인증 정보 유형: 컨테이너 레지스트리
- 인증 URL(Authentication URL):
ghcr.io - 사용자 이름(Username): GitHub 사용자명
- 비밀번호 또는 토큰(Password or Token):
read:packages권한의 classic 토큰- 빌드용 토큰(
write:packages)과 따로 만들어 최소 권한으로 쓰는 것을 권장한다.
- 빌드용 토큰(
- SSL 확인 체크

실행 환경 생성
- 관리 → 실행 환경 → 추가
- 이미지: 이미지 주소와 태그를 입력한다. 예:
ghcr.io/susoterran/jslim-awx-ee:1.0.0 - 레지스트리 인증 정보: 앞에서 만든 인증 정보를 선택한다.
- Pull: 이미지를 언제 받아올지 정한다.
devel처럼 같은 이름으로 계속 덮어쓰는 태그는 “항상”을,1.0.0처럼 고정된 버전 태그는 “존재하지 않는 경우에만”을 고르면 불필요한 pull을 줄일 수 있다.

- 이미지 주소는 GitHub 레포지토리의 Packages 화면에서 확인할 수 있다.

템플릿에 실행 환경 지정
- 리소스 → 템플릿 → 추가(또는 편집) → 실행 환경에서 앞서 만든 실행 환경을 선택한다.
- 실행 환경은 여러 개 등록할 수 있다. 앞에서 말한 구형 호스트용 EE처럼 템플릿마다 다른 EE를 고를 수 있다.

트러블슈팅
EPEL은 prepend_base에서 활성화한다
- 처음에는
system목록에epel-release를 넣었고, 목록 맨 위로 옮겨 보기도 했지만 해결되지 않았다. system목록은 순서가 의미가 없다. bindep 목록 전체가 한 번의 dnf 명령으로 설치되므로, 같은 명령 안에서 저장소를 먼저 켜고 그 저장소의 패키지를 설치할 수 없다.- 또
python_interpreter의 Python 패키지는 base 단계에서 설치되는데,system패키지는 그보다 뒤 단계에서 설치된다. - 그래서 base 단계가 시작되자마자 실행되는
prepend_base에서 EPEL을 설치하고 CRB를 활성화했다.
additional_build_steps:
prepend_base:
- RUN /usr/bin/dnf install -y epel-release
- RUN /usr/bin/crb enable
Python 버전을 올리면 binary 패키지 버전도 점검한다
psycopg[binary]처럼 미리 빌드된 바이너리(wheel)로 설치하는 패키지는 이미지의 Python 버전용 wheel이 있어야 설치된다.- 처음 고정했던
psycopg[binary]==3.1.8은 Python 3.13보다 먼저 나온 버전이라 3.13용 wheel이 없다. 그래서>=3.2.3으로 조건을 바꿨다.
참고자료
- https://github.com/ansible/awx-ee
- https://docs.ansible.com/projects/builder/en/latest/definition/
- https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html
- https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry
- https://wikidocs.net/230469
- https://blog.pages.kr/2830