Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements around the container image distribution #385

Merged
merged 14 commits into from
Oct 26, 2023
Merged
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ node_modules
.vscode
.github
.git
db_username.txt
db_password.txt
redis_password.txt
typesense_api_key.txt
.phpunit.result.cache
.env
docker-compose.yml
121 changes: 91 additions & 30 deletions .github/workflows/container-image-release.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
name: Container Image Release
concurrency: production
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
permissions:
packages: write
contents: read
on:
release:
types: [published]
workflow_dispatch:
inputs:
image_tag:
description: 'Image tag'
required: true
default: 'nightly-<put_date_here>'

env:
REGISTRY_IMAGE: ghcr.io/jikan-me/jikan-rest

jobs:
release-app-image:
build-app-image:
runs-on: ubuntu-latest
name: Release App container image
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
name: Build App container image
steps:
- name: Check if base container image exists
id: baseImageExists
run: |
GHCR_TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64)
curl --fail -H "Authorization: Bearer ${GHCR_TOKEN}" https://ghcr.io/v2/jikan-me/jikan-rest-php/tags/list | grep -q latest

- name: Base image existance check failed
if: ${{ always() && steps.baseImageExists.outcome == 'failure' }}
run: echo "Base image doesn't exist yet. Please run the base image creation workflow first."

- name: Checkout
uses: actions/checkout@v4
with:
Expand All @@ -29,18 +39,75 @@ jobs:

- name: Set up docker buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64

- name: Read metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
labels: |
org.opencontainers.image.title=Jikan REST API
org.opencontainers.image.description=REST API for Jikan
org.opencontainers.image.url=https://jikan.moe
org.opencontainers.image.source=https://github.com/jikan-me/jikan-rest

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v4
with:
context: .
platforms: ${{ matrix.platform }}
# let's use github action cache storage
cache-from: type=gha
cache-to: type=gha,mode=max
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true

- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v3
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

publish-app-image:
runs-on: ubuntu-latest
name: Publish app container image
needs:
- build-app-image
steps:
- name: Download digests
uses: actions/download-artifact@v3
with:
name: digests
path: /tmp/digests

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

- name: Read metadata
id: meta
uses: docker/metadata-action@v4
with:
images: |
ghcr.io/jikan-me/jikan-rest
${{ env.REGISTRY_IMAGE }}
jikanme/jikan-rest
tags: |
type=raw,value=${{ github.ref_name }}
type=raw,value=${{ inputs.image_tag || github.ref_name }}
type=sha

- name: Login to GitHub Container Registry
Expand All @@ -56,16 +123,10 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
context: .
# let's use github action cache storage
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
GITHUB_PERSONAL_TOKEN=${{ secrets.GITHUB_TOKEN }}
BASE_IMAGE_VERSION=latest
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ composer.phar
/coverage
.DS_Store
*.cache
db_username.txt
db_admin_username.txt
db_password.txt
db_admin_password.txt
redis_password.txt
typesense_api_key.txt
2 changes: 1 addition & 1 deletion .rr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ logs:

# we want to use docker's log drivers, so push logs to stdout
output: stdout
# we to use docker's log drivers, so push error logs to stdout
# we want to use docker's log drivers, so push error logs to stdout
# this way it is possible for example to pipe logs to journald or to AWS Cloudwatch
err_output: stdout

Expand Down
21 changes: 6 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
FROM spiralscout/roadrunner:2.12.2 as roadrunner
FROM composer:2.5.1 as composer
FROM mlocati/php-extension-installer:1.5.52 as php-ext-installer
FROM docker.io/spiralscout/roadrunner:2.12.2 as roadrunner
FROM docker.io/composer:2.5.1 as composer
FROM docker.io/mlocati/php-extension-installer:2.1.58 as php-ext-installer
FROM php:8.1.16-bullseye
ARG GITHUB_PERSONAL_TOKEN
COPY --from=composer /usr/bin/composer /usr/bin/composer
COPY --from=php-ext-installer /usr/bin/install-php-extensions /usr/local/bin/
ENV COMPOSER_HOME="/tmp/composer"
RUN set -x \
&& install-php-extensions gd exif intl bz2 gettext mongodb-stable redis opcache sockets pcntl \
&& install-php-extensions intl mbstring mongodb-stable redis opcache sockets pcntl \
# install xdebug (for testing with code coverage), but do not enable it
&& IPE_DONT_ENABLE=1 install-php-extensions xdebug-3.2.0

# install roadrunner
COPY --from=roadrunner /usr/bin/rr /usr/bin/rr
LABEL org.opencontainers.image.source=https://github.com/jikan-me/jikan-rest
# used only for supercronic atm. Supported values are: amd64, arm64
ARG TARGET_ARCH="amd64"
RUN set -ex \
&& apt-get update && apt-get install -y --no-install-recommends \
openssl \
git \
dos2unix \
wget \
unzip \
wget \
# install supercronic (for laravel task scheduling), project page: <https://github.com/aptible/supercronic>
&& wget -q "https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-${TARGET_ARCH}" \
&& wget -q "https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-$(dpkg --print-architecture)" \
-O /usr/bin/supercronic \
&& chmod +x /usr/bin/supercronic \
&& mkdir /etc/supercronic \
Expand All @@ -51,11 +47,6 @@ WORKDIR /app
# copy composer (json|lock) files for dependencies layer caching
COPY --chown=jikanapi:jikanapi ./composer.* /app/

# check if GITHUB_PERSONAL_TOKEN is set and configure it for composer
# it is recommended to set this for the build, otherwise the build might fail because of github's rate limits
RUN if [ -z "$GITHUB_PERSONAL_TOKEN" ]; then echo "** GITHUB_PERSONAL_TOKEN is not set. This build may fail due to github rate limits."; \
else composer config github-oauth.github.com "$GITHUB_PERSONAL_TOKEN"; fi

# install composer dependencies (autoloader MUST be generated later!)
RUN composer install -n --no-dev --no-cache --no-ansi --no-autoloader --no-scripts --prefer-dist

Expand Down
32 changes: 10 additions & 22 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,8 @@

namespace App\Console;

use App\Console\Commands\ClearQueuedJobs;
use App\Console\Commands\CacheRemove;
use App\Console\Commands\Indexer\AnimeIndexer;
use App\Console\Commands\Indexer\AnimeSweepIndexer;
use App\Console\Commands\Indexer\AnimeScheduleIndexer;
use App\Console\Commands\Indexer\CommonIndexer;
use App\Console\Commands\Indexer\CurrentSeasonIndexer;
use App\Console\Commands\Indexer\GenreIndexer;
use App\Console\Commands\Indexer\MangaIndexer;
use App\Console\Commands\Indexer\MangaSweepIndexer;
use App\Console\Commands\Indexer\ProducersIndexer;
use App\Console\Commands\ManageMicrocaching;
use App\Console\Commands\ModifyCacheDriver;
use App\Console\Commands\ModifyCacheMethod;
use App\Console\Commands\Indexer;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;

Expand All @@ -28,15 +16,15 @@ class Kernel extends ConsoleKernel
*/
protected $commands = [
CacheRemove::class,
CommonIndexer::class,
AnimeScheduleIndexer::class,
CurrentSeasonIndexer::class,
AnimeIndexer::class,
MangaIndexer::class,
GenreIndexer::class,
ProducersIndexer::class,
AnimeSweepIndexer::class,
MangaSweepIndexer::class,
Indexer\CommonIndexer::class,
Indexer\AnimeScheduleIndexer::class,
Indexer\CurrentSeasonIndexer::class,
Indexer\AnimeIndexer::class,
Indexer\MangaIndexer::class,
Indexer\GenreIndexer::class,
Indexer\ProducersIndexer::class,
Indexer\AnimeSweepIndexer::class,
Indexer\MangaSweepIndexer::class
];

/**
Expand Down
Loading