Skip to content
Open
Show file tree
Hide file tree
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
88 changes: 65 additions & 23 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,19 @@ jobs:
runs-on: ubuntu-latest
outputs:
timestamp: ${{ steps.timestamp.outputs.timestamp }}
datestamp: ${{ steps.timestamp.outputs.datestamp }}
steps:
- id: timestamp
run: |
timestamp=$(date +%Y%m%d-%H%M)
datestamp=$(echo $timestamp | sed -e 's/-.*$//')
echo "timestamp=$timestamp"
echo "datestamp=$datestamp"
echo "timestamp=$timestamp" >> $GITHUB_OUTPUT
echo "datestamp=$datestamp" >> $GITHUB_OUTPUT

# run all targets individually for cache, otherwise this may break caching
# possibly related to https://github.com/docker/buildx/issues/414
base:
# `cdck-linux-8-core` for amd64 builds
# `ubuntu-24.04-8core-arm` for arm64 builds
Expand All @@ -43,111 +49,136 @@ jobs:
working-directory: image
env:
TIMESTAMP: ${{ needs.timestamp.outputs.timestamp }}
DATESTAMP: ${{ needs.timestamp.outputs.datestamp }}
ARCH: ${{ matrix.arch }}
CACHE_IMAGE: ghcr.io/${{ github.repository }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1

- uses: docker/setup-buildx-action@v3
- name: Login to cache registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build runtime deps
- name: Build deps
run: |
docker buildx bake base-runtime-deps --no-cache --load
docker buildx bake base-runtime-deps -f docker-bake.hcl -f docker-bake.cache.hcl --load

- name: Build slim image
run: |
docker buildx bake base-slim --load
docker buildx bake base-slim-main -f docker-bake.hcl -f docker-bake.cache.hcl
docker buildx bake base-slim-stable -f docker-bake.hcl -f docker-bake.cache.hcl

- name: Build web only image
run: |
docker buildx bake base-web-only --load
docker buildx bake base-web-only-main -f docker-bake.hcl -f docker-bake.cache.hcl --load
docker buildx bake base-web-only-stable -f docker-bake.hcl -f docker-bake.cache.hcl --load

- name: Build release image
run: |
docker buildx bake base-release --load
docker buildx bake base-release-main -f docker-bake.hcl -f docker-bake.cache.hcl --load
docker buildx bake base-release-stable -f docker-bake.hcl -f docker-bake.cache.hcl --load

- name: Build test images
run: |
docker buildx bake test-release-${{ matrix.arch }} --load
docker buildx bake test-release -f docker-bake.hcl -f docker-bake.cache.hcl --load

- name: run specs for `main` branch
if: vars.SKIP_TESTS != '1'
run: |
docker run --rm -e RUBY_ONLY=1 -e USE_TURBO=1 -e SKIP_PLUGINS=1 -e SKIP_LINT=1 -e DISCOURSE_TURBO_RSPEC_RETRY_AND_LOG_FLAKY_TESTS=1 ${TEST_IMAGE}:release-${{ matrix.arch }}
docker run --rm -e RUBY_ONLY=1 -e USE_TURBO=1 -e SKIP_PLUGINS=1 -e SKIP_LINT=1 -e DISCOURSE_TURBO_RSPEC_RETRY_AND_LOG_FLAKY_TESTS=1 ${TEST_IMAGE}:release

- name: Build and push test image
if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
run: |
docker buildx bake test --set="*.tags=${TEST_IMAGE}" --set="*.output=type=registry,push-by-digest=true" --metadata-file=/tmp/test.json
docker buildx bake test-slim -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/test-slim.json
docker buildx bake test-slim-browsers -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/test-slim-browsers.json
docker buildx bake test-release -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/test-release.json

- name: Build and push dev image
if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
run: |
docker buildx bake dev --set="*.tags=${DEV_IMAGE}" --set="*.output=type=registry,push-by-digest=true" --allow=fs.read=../templates --metadata-file=/tmp/dev.json
docker buildx bake --allow=fs.read=../templates dev -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/dev.json

- name: Print summary
run: |
docker images ${BASE_IMAGE}

- name: Print `docker history` summary for main branch image
run: |
docker history ${BASE_IMAGE}:release-main-${{ matrix.arch }}
docker history ${BASE_IMAGE}:release-main

- name: push to dockerhub
if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
run: |
docker buildx bake base --set="*.tags=${BASE_IMAGE}" --set="*.output=type=registry,push-by-digest=true" --metadata-file=/tmp/base.json
docker buildx bake base-runtime-deps -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-runtime-deps.json
docker buildx bake base-slim-main -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-slim-main.json
docker buildx bake base-slim-stable -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-slim-stable.json
docker buildx bake base-web-only-main -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-web-only-main.json
docker buildx bake base-web-only-stable -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-web-only-stable.json
docker buildx bake base-release-main -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-release-main.json
docker buildx bake base-release-stable -f docker-bake.hcl -f docker-bake.push.hcl -f docker-bake.cache.hcl -f docker-bake.cache-write.hcl --metadata-file=/tmp/base-release-stable.json

- name: save image digests
if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
id: metadata
run: |
test_slim_${{ matrix.arch }}=$(jq -r '."test-slim-${{ matrix.arch }}"["containerimage.digest"]' /tmp/test.json)
test_slim_${{ matrix.arch }}=$(jq -r '."test-slim"["containerimage.digest"]' /tmp/test-slim.json)
echo "test_slim_${{ matrix.arch }}=$test_slim_${{ matrix.arch }}"
echo "test_slim_${{ matrix.arch }}=$test_slim_${{ matrix.arch }}" >> $GITHUB_OUTPUT

test_slim_browsers_${{ matrix.arch }}=$(jq -r '."test-slim-browsers-${{ matrix.arch }}"["containerimage.digest"]' /tmp/test.json)
test_slim_browsers_${{ matrix.arch }}=$(jq -r '."test-slim-browsers"["containerimage.digest"]' /tmp/test-slim-browsers.json)
echo "test_slim_browsers_${{ matrix.arch }}=$test_slim_browsers_${{ matrix.arch }}"
echo "test_slim_browsers_${{ matrix.arch }}=$test_slim_browsers_${{ matrix.arch }}" >> $GITHUB_OUTPUT

test_release_${{ matrix.arch }}=$(jq -r '."test-release-${{ matrix.arch }}"["containerimage.digest"]' /tmp/test.json)
test_release_${{ matrix.arch }}=$(jq -r '."test-release"["containerimage.digest"]' /tmp/test-release.json)
echo "test_release_${{ matrix.arch }}=$test_release_${{ matrix.arch }}"
echo "test_release_${{ matrix.arch }}=$test_release_${{ matrix.arch }}" >> $GITHUB_OUTPUT

dev_${{ matrix.arch }}=$(jq -r '."dev-${{ matrix.arch }}"["containerimage.digest"]' /tmp/dev.json)
dev_${{ matrix.arch }}=$(jq -r '."dev"["containerimage.digest"]' /tmp/dev.json)
echo "dev_${{ matrix.arch }}=$dev_${{ matrix.arch }}"
echo "dev_${{ matrix.arch }}=$dev_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_slim_main_${{ matrix.arch }}=$(jq -r '."base-slim-main-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_runtime_deps_${{ matrix.arch }}=$(jq -r '."base-runtime-deps"["containerimage.digest"]' /tmp/base-runtime-deps.json)
echo "base_runtime_deps_${{ matrix.arch }}=$base_runtime_deps_${{ matrix.arch }}"
echo "base_runtime_deps_${{ matrix.arch }}=$base_runtime_deps_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_slim_main_${{ matrix.arch }}=$(jq -r '."base-slim-main"["containerimage.digest"]' /tmp/base-slim-main.json)
echo "base_slim_main_${{ matrix.arch }}=$base_slim_main_${{ matrix.arch }}"
echo "base_slim_main_${{ matrix.arch }}=$base_slim_main_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_slim_stable_${{ matrix.arch }}=$(jq -r '."base-slim-stable-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_slim_stable_${{ matrix.arch }}=$(jq -r '."base-slim-stable"["containerimage.digest"]' /tmp/base-slim-stable.json)
echo "base_slim_stable_${{ matrix.arch }}=$base_slim_stable_${{ matrix.arch }}"
echo "base_slim_stable_${{ matrix.arch }}=$base_slim_stable_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_web_only_main_${{ matrix.arch }}=$(jq -r '."base-web-only-main-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_web_only_main_${{ matrix.arch }}=$(jq -r '."base-web-only-main"["containerimage.digest"]' /tmp/base-web-only-main.json)
echo "base_web_only_main_${{ matrix.arch }}=$base_web_only_main_${{ matrix.arch }}"
echo "base_web_only_main_${{ matrix.arch }}=$base_web_only_main_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_web_only_stable_${{ matrix.arch }}=$(jq -r '."base-web-only-stable-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_web_only_stable_${{ matrix.arch }}=$(jq -r '."base-web-only-stable"["containerimage.digest"]' /tmp/base-web-only-stable.json)
echo "base_web_only_stable_${{ matrix.arch }}=$base_web_only_stable_${{ matrix.arch }}"
echo "base_web_only_stable_${{ matrix.arch }}=$base_web_only_stable_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_release_main_${{ matrix.arch }}=$(jq -r '."base-release-main-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_release_main_${{ matrix.arch }}=$(jq -r '."base-release-main"["containerimage.digest"]' /tmp/base-release-main.json)
echo "base_release_main_${{ matrix.arch }}=$base_release_main_${{ matrix.arch }}"
echo "base_release_main_${{ matrix.arch }}=$base_release_main_${{ matrix.arch }}" >> $GITHUB_OUTPUT

base_release_stable_${{ matrix.arch }}=$(jq -r '."base-release-stable-${{ matrix.arch }}"["containerimage.digest"]' /tmp/base.json)
base_release_stable_${{ matrix.arch }}=$(jq -r '."base-release-stable"["containerimage.digest"]' /tmp/base-release-stable.json)
echo "base_release_stable_${{ matrix.arch }}=$base_release_stable_${{ matrix.arch }}"
echo "base_release_stable_${{ matrix.arch }}=$base_release_stable_${{ matrix.arch }}" >> $GITHUB_OUTPUT
outputs:
base_runtime_deps_amd64: ${{ steps.metadata.outputs.base_runtime_deps_amd64 }}
base_runtime_deps_arm64: ${{ steps.metadata.outputs.base_runtime_deps_arm64 }}
base_slim_main_amd64: ${{ steps.metadata.outputs.base_slim_main_amd64 }}
base_slim_main_arm64: ${{ steps.metadata.outputs.base_slim_main_arm64 }}
base_slim_stable_amd64: ${{ steps.metadata.outputs.base_slim_stable_amd64 }}
Expand Down Expand Up @@ -195,11 +226,12 @@ jobs:

- name: build and push to dockerhub
run: |
docker buildx bake setup-wizard --set="*.tags=${SETUP_WIZARD_IMAGE}" --set="*.output=type=registry,push-by-digest=true" --metadata-file=/tmp/setup-wizard.json
docker buildx bake setup-wizard -f docker-bake.hcl -f docker-bake.push.hcl --metadata-file=/tmp/setup-wizard.json

- name: save image digests
id: metadata
run: |
${{ matrix.arch }}=$(jq -r '."setup-wizard-${{ matrix.arch }}"["containerimage.digest"]' /tmp/setup-wizard.json)
${{ matrix.arch }}=$(jq -r '."setup-wizard"["containerimage.digest"]' /tmp/setup-wizard.json)
echo "${{ matrix.arch }}=$${{ matrix.arch }}"
echo "${{ matrix.arch }}=$${{ matrix.arch }}" >> $GITHUB_OUTPUT
outputs:
Expand Down Expand Up @@ -232,6 +264,16 @@ jobs:
${{ needs.base.outputs.base_slim_main_amd64 }} \
${{ needs.base.outputs.base_slim_main_arm64 }}

# runtime-deps timestamped
docker buildx imagetools create -t ${BASE_IMAGE}:2.0.${{ env.TIMESTAMP }}-runtime-deps \
${{ needs.base.outputs.base_runtime_deps_amd64 }} \
${{ needs.base.outputs.base_runtime_deps_arm64 }}

# runtime-deps release
docker buildx imagetools create -t ${BASE_IMAGE}:runtime-deps \
${{ needs.base.outputs.base_runtime_deps_amd64 }} \
${{ needs.base.outputs.base_runtime_deps_arm64 }}

# Web-Only `main` timestamped
docker buildx imagetools create -t ${BASE_IMAGE}:2.0.${{ env.TIMESTAMP }}-web-only \
${{ needs.base.outputs.base_web_only_main_amd64 }} \
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/cleanup-cache.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
on:
push:
branches:
- main
schedule:
- cron: "0 0 * * *"

jobs:
cleanup_cache:
runs-on: ubuntu-latest
steps:
- name: cleanup cache
env:
GH_TOKEN: ${{ secrets.GH_CLEANUP_CACHE_TOKEN }}
PACKAGE_NAME: discourse_docker
run: |
if [[ -z "$GH_TOKEN" ]]; then
echo "no cleanup token set, set cleanup token by setting an access token for secrets.GH_CLEANUP_CACHE_TOKEN with delete:packages, read:org permissions"
exit 0
fi
# figure out if this is a user or organization repository
OWNER_TYPE=$(gh api /users/${{ github.repository_owner }} --jq '.type')
if [[ "$OWNER_TYPE" == "User" ]]; then
OWNER_TYPE="users"
else
OWNER_TYPE="orgs"
fi
gh api /${OWNER_TYPE}/${{ github.repository_owner }}/packages/container/discourse_docker/versions --paginate > /tmp/dangling_ids.txt
ids_to_delete=$(cat /tmp/dangling_ids.txt | jq -r '.[] | select(.metadata.container.tags==[]) | .id')
if [ "${ids_to_delete}" = "" ]
then
echo "There are no dangling images to remove for this package"
exit 0
fi
echo "Deleting dangling ids..."
while read -r id; do
gh api --method DELETE /${OWNER_TYPE}/${{ github.repository_owner }}/packages/container/${PACKAGE_NAME}/versions/${id}
echo Dangling image with ID $id deleted successfully
done <<< $ids_to_delete
26 changes: 14 additions & 12 deletions image/base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
ARG DEBIAN_RELEASE=bookworm
ARG RUBY_VERSION=3.4.9
ARG FROM_DOCKER_IMAGE_TAG=${RUBY_VERSION}-${DEBIAN_RELEASE}-slim
ARG DATESTAMP=0

FROM discourse/ruby:${FROM_DOCKER_IMAGE_TAG} AS builder
ARG DATESTAMP
ARG DEBIAN_RELEASE
ENV DEBIAN_RELEASE=${DEBIAN_RELEASE}
RUN echo "deb http://deb.debian.org/debian ${DEBIAN_RELEASE}-backports main" > "/etc/apt/sources.list.d/${DEBIAN_RELEASE}-backports.list"
Expand All @@ -20,17 +22,17 @@ DEBIAN_FRONTEND=noninteractive apt-get -y install wget \
libbrotli-dev

FROM builder AS imagemagick_builder
ADD install-imagemagick /tmp/install-imagemagick
COPY install-imagemagick /tmp/install-imagemagick
RUN /tmp/install-imagemagick

FROM builder AS vips-builder
ADD install-vips /tmp/install-vips
COPY install-vips /tmp/install-vips
RUN /tmp/install-vips

FROM builder AS nginx-builder
# From https://nginx.org/en/pgp_keys.html
ADD nginx_public_keys.key /tmp/nginx_public_keys.key
ADD install-nginx /tmp/install-nginx
COPY nginx_public_keys.key /tmp/nginx_public_keys.key
COPY install-nginx /tmp/install-nginx
RUN gpg --import /tmp/nginx_public_keys.key &&\
rm /tmp/nginx_public_keys.key &&\
/tmp/install-nginx
Expand All @@ -39,23 +41,23 @@ FROM builder AS thpoff-builder
# This tool allows us to disable huge page support for our current process
# since the flag is preserved through forks and execs it can be used on any
# process
ADD thpoff.c /src/thpoff.c
COPY thpoff.c /src/thpoff.c
RUN gcc -o /usr/local/sbin/thpoff /src/thpoff.c && rm /src/thpoff.c

FROM builder AS jemalloc-builder
ADD install-jemalloc /tmp/install-jemalloc
COPY install-jemalloc /tmp/install-jemalloc
RUN /tmp/install-jemalloc

FROM builder AS oxipng-builder
ADD install-oxipng /tmp/install-oxipng
COPY install-oxipng /tmp/install-oxipng
RUN /tmp/install-oxipng

FROM builder AS cjpegli-builder
ADD install-cjpegli /tmp/install-cjpegli
COPY install-cjpegli /tmp/install-cjpegli
RUN /tmp/install-cjpegli

FROM discourse/ruby:${FROM_DOCKER_IMAGE_TAG} AS discourse-runtime-base

ARG DATESTAMP
ARG DEBIAN_RELEASE
ARG PG_MAJOR=15
ENV PG_MAJOR=${PG_MAJOR} \
Expand Down Expand Up @@ -158,7 +160,7 @@ COPY --from=oxipng-builder /usr/local/bin/jhead /usr/local/bin
COPY --from=oxipng-builder /usr/local/bin/oxipng /usr/local/bin
COPY --from=cjpegli-builder /usr/local/bin/cjpegli /usr/local/bin

ADD install-redis /tmp/install-redis
COPY install-redis /tmp/install-redis

# version check: https://rubygems.org/gems/pups
RUN cd /tmp &&\
Expand All @@ -179,10 +181,10 @@ COPY sbin/ /sbin
FROM discourse-runtime-base AS discourse-build-base
# From https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key
# fingerprint: 6F71 F525 2828 41EE DAF8 51B4 2F59 B5F9 9B1B E0B4
ADD nodesource-repo.gpg.key /usr/share/keyrings/nodesource.asc
COPY nodesource-repo.gpg.key /usr/share/keyrings/nodesource.asc
# From https://dl.yarnpkg.com/debian/pubkey.gpg
# fingerprint: 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310
ADD yarn-pubkey.gpg.key /usr/share/keyrings/yarn.asc
COPY yarn-pubkey.gpg.key /usr/share/keyrings/yarn.asc
RUN --mount=type=tmpfs,target=/var/log \
--mount=type=tmpfs,target=/var/cache/apt \
--mount=type=tmpfs,target=/var/lib/apt \
Expand Down
6 changes: 3 additions & 3 deletions image/discourse_dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ RUN /tmp/install-redis
RUN rm -rf /var/www/*

# Give discourse user no-passwd sudo permissions (for bundle install)
ADD sudoers.discourse /etc/sudoers.d/discourse
COPY sudoers.discourse /etc/sudoers.d/discourse

RUN sudo -u discourse bundle config set --global path /home/discourse/.bundle/gems

Expand All @@ -45,15 +45,15 @@ RUN sed -e 's/\(db_name: discourse\)/\1_development/' /pups/postgres.template.ym
RUN LANG=en_US.UTF-8 /pups/bin/pups /pups/postgres.yml

# add dev databases
ADD postgres_dev.template.yml /pups/postgres_dev.yml
COPY postgres_dev.template.yml /pups/postgres_dev.yml
RUN /pups/bin/pups /pups/postgres_dev.yml

# move default postgres_data out of the way
RUN mv /shared/postgres_data /shared/postgres_data_orig

# re-instantiate data on boot if needed (this will allow it to persist across
# invocations when used with a mounted volume)
ADD ensure-database /etc/runit/1.d/ensure-database
COPY ensure-database /etc/runit/1.d/ensure-database

# Install & Configure MailHog (https://github.com/mailhog/MailHog)
RUN wget -qO /tmp/mailhog https://github.com/mailhog/MailHog/releases/download/v1.0.1/MailHog_linux_amd64\
Expand Down
Loading
Loading