Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 80 additions & 33 deletions .github/workflows/nomploy.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: Docker Publish (GHCR)

# Builds the nomploy app image and pushes it to the GitHub Container Registry.
# Uses the built-in GITHUB_TOKEN — no external registry secrets required.
# Builds a multi-arch (amd64 + arm64) app image and pushes it to the GitHub
# Container Registry using the built-in GITHUB_TOKEN — no external secrets.
#
# NOTE: the published package (ghcr.io/<owner>/nomploy) inherits the repo's
# visibility. For `install.sh` to `docker pull` without auth on a fresh server,
# set the package to Public in its GitHub package settings (or `docker login
# ghcr.io` on the server).
# Each architecture is built on its OWN native runner (fast, no QEMU emulation),
# pushed by digest, then a merge job assembles one multi-arch manifest. Native
# arm64 runners (ubuntu-24.04-arm) are free for public repositories.
#
# NOTE: for `install.sh` to `docker pull` without auth, the ghcr package must be
# Public (set it in the package settings once).

on:
push:
Expand All @@ -18,20 +20,27 @@ permissions:
contents: read
packages: write

env:
IMAGE: ghcr.io/nomploy/nomploy

jobs:
build-and-push:
runs-on: ubuntu-latest
timeout-minutes: 120
build:
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
arch: amd64
runner: ubuntu-latest
- platform: linux/arm64
arch: arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4

# QEMU lets a single amd64 runner also build the arm64 image (emulated).
# Simpler and plan-independent; slower than native arm runners. For faster
# builds, split into native amd64 + ubuntu-24.04-arm jobs with a manifest.
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

Expand All @@ -42,34 +51,72 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Compute lowercase image name
id: img
- name: Prepare env file
run: |
cp apps/dokploy/.env.production.example .env.production
cp apps/dokploy/.env.production.example apps/dokploy/.env.production

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=${{ matrix.arch }}

- name: Export digest
run: |
owner=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
echo "name=ghcr.io/${owner}/nomploy" >> "$GITHUB_OUTPUT"
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.arch }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

merge:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker metadata (tags + labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ steps.img.outputs.name }}
images: ${{ env.IMAGE }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=tag
type=sha,format=short

- name: Prepare env file
- name: Create and push multi-arch manifest
working-directory: /tmp/digests
run: |
cp apps/dokploy/.env.production.example .env.production
cp apps/dokploy/.env.production.example apps/dokploy/.env.production
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.IMAGE }}@sha256:%s ' *)

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Inspect image
run: docker buildx imagetools inspect ${{ env.IMAGE }}:latest
Loading