Skip to content

Commit ef64dd0

Browse files
AFCMSAlexTMjugador
andauthored
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 <[email protected]>
1 parent c81a863 commit ef64dd0

File tree

4 files changed

+141
-10
lines changed

4 files changed

+141
-10
lines changed

.dockerignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
scripts
2+
.github
3+
.editorconfig
4+
.pre-commit-hooks.yaml

.github/workflows/docker.yml

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: docker
2+
on:
3+
push:
4+
branches:
5+
- 'master'
6+
tags:
7+
- 'v*.*.*'
8+
pull_request:
9+
types:
10+
- opened
11+
- synchronize
12+
workflow_dispatch:
13+
inputs:
14+
use_cache:
15+
description: "Use build cache"
16+
required: true
17+
type: boolean
18+
default: true
19+
20+
env:
21+
REGISTRY: ghcr.io
22+
# ghcr.io/OWNER/REPO
23+
IMAGE_NAME: ${{ github.repository }}
24+
25+
jobs:
26+
build:
27+
runs-on: ubuntu-latest
28+
permissions:
29+
contents: read
30+
packages: write
31+
id-token: write
32+
attestations: write
33+
34+
steps:
35+
- name: Checkout repository
36+
uses: actions/checkout@v4
37+
38+
- name: Set up QEMU
39+
uses: docker/setup-qemu-action@v3
40+
41+
# Workaround: https://github.com/docker/build-push-action/issues/461
42+
- name: Setup Docker buildx
43+
uses: docker/setup-buildx-action@v3
44+
45+
# Login against a Docker registry except on PR
46+
# https://github.com/docker/login-action
47+
- name: Log into registry ${{ env.REGISTRY }}
48+
if: github.event_name != 'pull_request'
49+
uses: docker/login-action@v3
50+
with:
51+
registry: ${{ env.REGISTRY }}
52+
username: ${{ github.actor }}
53+
password: ${{ secrets.GITHUB_TOKEN }}
54+
55+
# Extract metadata (tags, labels) for Docker
56+
# For some reason the title have to be set manually
57+
# https://github.com/docker/metadata-action
58+
- name: Extract Docker metadata
59+
id: meta
60+
uses: docker/metadata-action@v5
61+
with:
62+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
63+
labels: |
64+
org.opencontainers.image.title=Oxipng
65+
annotations: |
66+
org.opencontainers.image.title=Oxipng
67+
68+
# Build and push Docker image with Buildx (don't push on PR)
69+
# Cache isn't used for tags and on workflow_dispatch if specified
70+
# https://github.com/docker/build-push-action
71+
- name: Build and push Docker image
72+
id: build-and-push
73+
uses: docker/build-push-action@v6
74+
with:
75+
context: .
76+
platforms: linux/amd64,linux/arm64
77+
push: ${{ github.event_name != 'pull_request' }}
78+
tags: ${{ steps.meta.outputs.tags }}
79+
labels: ${{ steps.meta.outputs.labels }}
80+
cache-from: type=gha
81+
cache-to: type=gha,mode=max
82+
no-cache: ${{ (github.event_name == 'workflow_dispatch' && !inputs.use_cache) || startsWith(github.ref, 'refs/tags/') }}
83+
84+
# Attest the build provenance
85+
# TODO: enable push to registry when referrers API will be supported by ghcr.io
86+
- name: Attest Build Provenance
87+
if: github.event_name != 'pull_request'
88+
uses: actions/attest-build-provenance@v1
89+
with:
90+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
91+
subject-digest: ${{ steps.build-and-push.outputs.digest }}
92+
push-to-registry: false

Dockerfile

+35-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,45 @@
1-
FROM rust:alpine as base
1+
# syntax=docker/dockerfile:1
2+
FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx
23

3-
COPY . /src
4+
FROM --platform=$BUILDPLATFORM rust:1.74-alpine AS base
45

5-
RUN rustup update 1.74 && rustup default 1.74
6-
7-
RUN apk update \
8-
&& apk add \
6+
RUN apk update && \
7+
apk add \
98
gcc \
10-
g++
9+
g++ \
10+
clang
1111

12-
RUN cd /src && cargo build --release
12+
COPY --from=xx / /
1313

14-
FROM alpine as tool
14+
ARG TARGETPLATFORM
15+
RUN xx-info env
1516

16-
COPY --from=base /src/target/release/oxipng /usr/local/bin
17+
RUN xx-apk add \
18+
gcc \
19+
musl-dev \
20+
libdeflate
1721

1822
WORKDIR /src
23+
24+
COPY . .
25+
26+
RUN --mount=type=cache,target=/root/.cargo/git/db \
27+
--mount=type=cache,target=/root/.cargo/registry/cache \
28+
--mount=type=cache,target=/root/.cargo/registry/index \
29+
xx-cargo build --release && \
30+
xx-verify /src/target/$(xx-cargo --print-target-triple)/release/oxipng && \
31+
cp /src/target/$(xx-cargo --print-target-triple)/release/oxipng /src/target/oxipng
32+
33+
FROM alpine AS tool
34+
35+
LABEL org.opencontainers.image.title="Oxipng"
36+
LABEL org.opencontainers.image.description="Multithreaded PNG optimizer written in Rust"
37+
LABEL org.opencontainers.image.authors="Joshua Holmer <[email protected]>"
38+
LABEL org.opencontainers.image.licenses="MIT"
39+
LABEL org.opencontainers.image.source="https://github.com/shssoichiro/oxipng"
40+
41+
COPY --from=base /src/target/oxipng /usr/local/bin
42+
43+
WORKDIR /work
1944
ENTRYPOINT [ "oxipng" ]
2045
CMD [ "--help" ]

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ trunk actions enable trunk-fmt-pre-commit
133133

134134
[trunk]: https://docs.trunk.io
135135

136+
## Docker
137+
138+
A Docker image is availlable at `ghcr.io/shssoichiro/oxipng` for `linux/amd64` and `linux/arm64`.
139+
140+
You can use it the following way:
141+
142+
```bash
143+
docker run --rm -v $(pwd):/work ghcr.io/shssoichiro/oxipng -o 4 /work/file.png
144+
```
145+
136146
## Library Usage
137147

138148
Although originally intended to be used as an executable, oxipng can also be used as a library in

0 commit comments

Comments
 (0)