Skip to content

Commit 02c67b4

Browse files
committed
Add Docker image and multi-arch CI build
Multi-stage build on debian:13-slim: a build stage with ccache and Ninja, a slim runtime stage with only the shared libraries the server links against. The server binary is the image ENTRYPOINT. The Docker workflow builds linux/amd64 and linux/arm64 natively on their respective GitHub-hosted runners, pushes each by digest to GHCR, and merges them into a single multi-arch manifest.
1 parent 2efabc7 commit 02c67b4

3 files changed

Lines changed: 168 additions & 0 deletions

File tree

‎.dockerignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.git
2+
build
3+
Dockerfile
4+
.dockerignore

‎.github/workflows/docker.yml‎

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: Docker
2+
3+
on:
4+
push:
5+
branches: [master]
6+
tags: ['v*']
7+
pull_request:
8+
branches: [master]
9+
workflow_dispatch:
10+
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: ${{ github.repository }}
14+
15+
jobs:
16+
build:
17+
name: Build ${{ matrix.platform }}
18+
runs-on: ${{ matrix.runner }}
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- platform: linux/amd64
24+
runner: ubuntu-24.04
25+
- platform: linux/arm64
26+
runner: ubuntu-24.04-arm
27+
permissions:
28+
contents: read
29+
packages: write
30+
steps:
31+
- name: Prepare platform pair
32+
run: |
33+
platform=${{ matrix.platform }}
34+
echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV"
35+
36+
- name: Checkout
37+
uses: actions/checkout@v5
38+
with:
39+
submodules: recursive
40+
41+
- name: Docker metadata
42+
id: meta
43+
uses: docker/metadata-action@v5
44+
with:
45+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
46+
47+
- name: Set up Docker Buildx
48+
uses: docker/setup-buildx-action@v3
49+
50+
- name: Log in to the Container registry
51+
if: github.event_name != 'pull_request'
52+
uses: docker/login-action@v3
53+
with:
54+
registry: ${{ env.REGISTRY }}
55+
username: ${{ github.actor }}
56+
password: ${{ secrets.GITHUB_TOKEN }}
57+
58+
- name: Build and push by digest
59+
id: build
60+
uses: docker/build-push-action@v6
61+
with:
62+
context: .
63+
platforms: ${{ matrix.platform }}
64+
labels: ${{ steps.meta.outputs.labels }}
65+
cache-from: type=gha,scope=${{ env.PLATFORM_PAIR }}
66+
cache-to: type=gha,mode=max,scope=${{ env.PLATFORM_PAIR }}
67+
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
68+
69+
- name: Export digest
70+
if: github.event_name != 'pull_request'
71+
run: |
72+
mkdir -p "${{ runner.temp }}/digests"
73+
digest="${{ steps.build.outputs.digest }}"
74+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
75+
76+
- name: Upload digest
77+
if: github.event_name != 'pull_request'
78+
uses: actions/upload-artifact@v5
79+
with:
80+
name: digests-${{ env.PLATFORM_PAIR }}
81+
path: ${{ runner.temp }}/digests/*
82+
if-no-files-found: error
83+
retention-days: 1
84+
85+
merge:
86+
name: Merge and push manifest
87+
runs-on: ubuntu-24.04
88+
needs: build
89+
if: github.event_name != 'pull_request'
90+
permissions:
91+
contents: read
92+
packages: write
93+
steps:
94+
- name: Download digests
95+
uses: actions/download-artifact@v5
96+
with:
97+
path: ${{ runner.temp }}/digests
98+
pattern: digests-*
99+
merge-multiple: true
100+
101+
- name: Set up Docker Buildx
102+
uses: docker/setup-buildx-action@v3
103+
104+
- name: Docker metadata
105+
id: meta
106+
uses: docker/metadata-action@v5
107+
with:
108+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
109+
tags: |
110+
type=ref,event=branch
111+
type=ref,event=tag
112+
type=sha
113+
114+
- name: Log in to the Container registry
115+
uses: docker/login-action@v3
116+
with:
117+
registry: ${{ env.REGISTRY }}
118+
username: ${{ github.actor }}
119+
password: ${{ secrets.GITHUB_TOKEN }}
120+
121+
- name: Create manifest list and push
122+
working-directory: ${{ runner.temp }}/digests
123+
run: |
124+
docker buildx imagetools create \
125+
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
126+
$(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
127+
128+
- name: Inspect image
129+
run: |
130+
docker buildx imagetools inspect \
131+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}

‎Dockerfile‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM debian:13-slim AS build
2+
3+
RUN apt-get update \
4+
&& apt-get install -y --no-install-recommends \
5+
g++ make cmake git gperf libssl-dev zlib1g-dev ccache ninja-build \
6+
&& rm -rf /var/lib/apt/lists/*
7+
8+
WORKDIR /src
9+
COPY . .
10+
11+
ENV CCACHE_DIR=/ccache
12+
RUN --mount=type=cache,target=/ccache \
13+
cmake -S . -B build -G Ninja \
14+
-DCMAKE_BUILD_TYPE=Release \
15+
-DCMAKE_INSTALL_PREFIX=/usr/local \
16+
&& cmake --build build --target install \
17+
&& ccache -s
18+
19+
FROM debian:13-slim
20+
21+
# openssl provides libssl/libcrypto whatever the versioned library package is
22+
# named; zlib1g is already in the base image but is listed explicitly since the
23+
# server links against it.
24+
RUN apt-get update \
25+
&& apt-get install -y --no-install-recommends ca-certificates openssl zlib1g \
26+
&& rm -rf /var/lib/apt/lists/*
27+
28+
COPY --from=build /usr/local/bin/telegram-bot-api /usr/local/bin/telegram-bot-api
29+
30+
WORKDIR /var/lib/telegram-bot-api
31+
EXPOSE 8081
32+
ENTRYPOINT ["/usr/local/bin/telegram-bot-api"]
33+
CMD ["--verbosity=2", "--temp-dir=/tmp/telegram-bot-api"]

0 commit comments

Comments
 (0)