Improved Docker image + publish on ghcr.io (#642)

Fix #610

- [x] Native cross-compilation support in Dockerfile. Only `linux/amd64`
and `linux/arm64` supported and tested (Tier 1 platform support from
Rust)
- [x] Cache support for cargo downloads and compilation results in
Dockerfile
- [x] Open Container's
[annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
in Dockerfile
- [x] GitHub Actions workflow to build the image for both platforms,
publishing to ghcr.io on tags and master branch pushes.
- [x] Disable use of GitHub Actions cache for tags build, allow manually
triggering the workflow with or without cache.
- [x] [Attestation
artifacts](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds)
for builds
- [x] Add basic informations about the use of the Docker image in README

I also changed the WORKDIR from `/src` to `/work`, because if got me
confused with the use of the src folder for the project source in the
first stage of the Dockerfile. It doesn't impact anything anyways since
you can mount the file where you want and have the program options point
to it.

**How to test?**
_After checking out the branch and making sure you have QEMU installed
to build/test_
```shell
# Docker sadly doesn't have yet the way to have locally a tag with multiple platforms
# despite being able to pass multiple platforms to the build command, so we have to use two distinct tags.
docker build --platform=linux/amd64 --tag test-oxipng-amd:latest --load .
docker build --platform=linux/arm64 --tag test-oxipng-arm:latest --load .

docker run --rm test-oxipng-amd:latest --version
docker run --rm test-oxipng-arm:latest --version

# Run on some files
docker run --rm -it -v $(pwd):/work test-oxipng-amd:latest -a /work/tests/files/apng_file.png
docker run --rm -it -v $(pwd):/work test-oxipng-arm:latest -a /work/tests/files/apng_file.png

# Remove the images
docker image rm test-oxipng-amd:latest
docker image rm test-oxipng-arm:latest
```

For the workflow, see the GitHub Actions logs. If you want to test the
ghcr.io publishing you can merge the branch into a fork and see the
result.

---------

Co-authored-by: Alejandro González <me@alegon.dev>
This commit is contained in:
AFCMS 2024-11-24 14:08:11 +01:00 committed by GitHub
parent c81a863e69
commit ef64dd0768
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 141 additions and 10 deletions

4
.dockerignore Normal file
View file

@ -0,0 +1,4 @@
scripts
.github
.editorconfig
.pre-commit-hooks.yaml

92
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,92 @@
name: docker
on:
push:
branches:
- 'master'
tags:
- 'v*.*.*'
pull_request:
types:
- opened
- synchronize
workflow_dispatch:
inputs:
use_cache:
description: "Use build cache"
required: true
type: boolean
default: true
env:
REGISTRY: ghcr.io
# ghcr.io/OWNER/REPO
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
attestations: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# For some reason the title have to be set manually
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: |
org.opencontainers.image.title=Oxipng
annotations: |
org.opencontainers.image.title=Oxipng
# Build and push Docker image with Buildx (don't push on PR)
# Cache isn't used for tags and on workflow_dispatch if specified
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
no-cache: ${{ (github.event_name == 'workflow_dispatch' && !inputs.use_cache) || startsWith(github.ref, 'refs/tags/') }}
# Attest the build provenance
# TODO: enable push to registry when referrers API will be supported by ghcr.io
- name: Attest Build Provenance
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: false

View file

@ -1,20 +1,45 @@
FROM rust:alpine as base
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx
COPY . /src
FROM --platform=$BUILDPLATFORM rust:1.74-alpine AS base
RUN rustup update 1.74 && rustup default 1.74
RUN apk update \
&& apk add \
RUN apk update && \
apk add \
gcc \
g++
g++ \
clang
RUN cd /src && cargo build --release
COPY --from=xx / /
FROM alpine as tool
ARG TARGETPLATFORM
RUN xx-info env
COPY --from=base /src/target/release/oxipng /usr/local/bin
RUN xx-apk add \
gcc \
musl-dev \
libdeflate
WORKDIR /src
COPY . .
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
xx-cargo build --release && \
xx-verify /src/target/$(xx-cargo --print-target-triple)/release/oxipng && \
cp /src/target/$(xx-cargo --print-target-triple)/release/oxipng /src/target/oxipng
FROM alpine AS tool
LABEL org.opencontainers.image.title="Oxipng"
LABEL org.opencontainers.image.description="Multithreaded PNG optimizer written in Rust"
LABEL org.opencontainers.image.authors="Joshua Holmer <jholmer.in@gmail.com>"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.source="https://github.com/shssoichiro/oxipng"
COPY --from=base /src/target/oxipng /usr/local/bin
WORKDIR /work
ENTRYPOINT [ "oxipng" ]
CMD [ "--help" ]

View file

@ -133,6 +133,16 @@ trunk actions enable trunk-fmt-pre-commit
[trunk]: https://docs.trunk.io
## Docker
A Docker image is availlable at `ghcr.io/shssoichiro/oxipng` for `linux/amd64` and `linux/arm64`.
You can use it the following way:
```bash
docker run --rm -v $(pwd):/work ghcr.io/shssoichiro/oxipng -o 4 /work/file.png
```
## Library Usage
Although originally intended to be used as an executable, oxipng can also be used as a library in