Skip to content

Commit 5a5ca2b

Browse files
authored
Merge pull request pmacct#847 from msune/docker_arm_support
* Docker: build and publish linux/arm64 images (experimental)
2 parents 56b7bb2 + a28355f commit 5a5ca2b

File tree

17 files changed

+316
-102
lines changed

17 files changed

+316
-102
lines changed

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ src/external_libs/rootfs
5151

5252
# Dockerfiles makes no sense in the build context
5353
**/Dockerfile
54+
55+
# Exclude Makefile (dev only)
56+
docker/Makefile

.github/workflows/ci.yaml

Lines changed: 64 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -107,40 +107,21 @@ jobs:
107107
docker exec -i $CONTAINER_ID ./ci/script.sh
108108
docker stop $CONTAINER_ID
109109
110-
### Step 3: official docker image generation
111-
pmacct-docker:
110+
### Step 3.1: test that local single-platform builds work fine
111+
docker-build-test-local:
112112
runs-on: ubuntu-22.04
113113
steps:
114114
- name: Checkout pmacct
115-
uses: actions/checkout@v4
115+
uses: actions/checkout@v1 #Don't use v2 messes everything
116116
with:
117117
path: pmacct
118-
fetch-depth: 0
119-
fetch-tags: 1
120118

121-
- name: Check DAEMONS env. variable...
119+
- name: Build single-platform
122120
run: |
123-
#Sanity, avoid regression #816
124-
N_DAEMONS="$(echo $DAEMONS | wc --words)"
125-
if [[ "${N_DAEMONS}" != "7" ]]; then
126-
echo "ERROR: invalid number of DAEMONS: ${N_DAEMONS}"
127-
exit 1
128-
fi
129-
130-
- name: Build containers
131-
uses: ./pmacct/.github/actions/build_containers/
132-
with:
133-
daemons: ${{env.DAEMONS}}
134-
135-
- name: Docker save images
136-
run: |
137-
echo "Saving images as artifacts..."
138-
mkdir -p /tmp/docker/
139-
docker save -o /tmp/docker/pmacct_docker_images.tar base:_build $(for DAEMON in ${DAEMONS};do echo "${DAEMON}:_build "; done)
121+
cd docker && V=1 make
140122
141123
- name: Docker (compose) smoke test
142124
run: |
143-
cd pmacct
144125
echo "Running smoke test using docker compose..."
145126
TAG=_build docker compose -f ci/smoke-test/docker-compose.yml up -d
146127
sleep 10
@@ -151,51 +132,31 @@ jobs:
151132
echo "Stopping containers..."
152133
TAG=_build docker compose -f ci/smoke-test/docker-compose.yml down
153134
154-
- name: Export pmacct docker images as an artifact
155-
uses: actions/upload-artifact@v4
156-
with:
157-
name: pmacct_docker_images
158-
retention-days: 1
159-
path: /tmp/docker
160-
161-
### Step 4: Upload images to dockerhub (bleeding-edge, latest and releases)
162-
publish-dockerhub:
163-
needs: [pmacct-docker, build-and-test]
135+
### Step 3.2: Build test and publish (bleeding-edge, latest and releases)
136+
docker-multiplatform-build-test-publish:
164137
runs-on: ubuntu-22.04
165-
if: github.event_name != 'pull_request' && vars.SKIP_DOCKERHUB_PUBLISH != 'true'
138+
needs: [build-and-test, docker-build-test-local]
166139
env:
167-
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
168-
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
140+
PLATFORMS: linux/amd64,linux/arm64
169141
steps:
170-
- uses: actions/download-artifact@v4
171-
with:
172-
name: pmacct_docker_images
173-
path: /tmp/docker
174-
175-
- name: Import pmacct docker images in the local registry
176-
run: |
177-
docker load -i /tmp/docker/pmacct_docker_images.tar
178-
179142
- name: Checkout pmacct
180143
uses: actions/checkout@v1 #Don't use v2 messes everything
181144
with:
182145
path: pmacct
183146

184-
- name: Build and upload containers
147+
- name: Deduce PMACCT version and tags
185148
run: |
186149
echo "Fix mess with tags in actions/checkout..."
187150
git fetch -f && git fetch -f --tags
188151
echo "Deducing PMACCT_VERSION..."
189152
PMACCT_VERSION=$(git describe --abbrev=0 --match="v*")
190-
echo "PMACCT_VERSION=$PMACCT_VERSION"
191-
echo "Uploading to dockerhub ...";
192-
echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USERNAME} --password-stdin;
193153
194154
#Always push bleeding-edge when pushed to master
195155
GIT_IS_BLEEDING_EDGE=$( (git branch --all --contains HEAD | grep master ) || echo "")
196156
echo "GIT_IS_BLEEDING_EDGE=$GIT_IS_BLEEDING_EDGE"
197157
if [ "$GIT_IS_BLEEDING_EDGE" != "" ]; then
198158
echo "Tagging and uploading 'bleeding-edge'..."
159+
TAGS="$TAGS bleeding-edge"
199160
else
200161
echo "NOT uploading 'bleeding-edge'... Not HEAD of master"
201162
fi
@@ -205,32 +166,69 @@ jobs:
205166
if [ "$GIT_RELEASE_TAG" != "" ]; then
206167
echo "GIT_RELEASE_TAG=$GIT_RELEASE_TAG"
207168
echo "Tagging and uploading release '$GIT_RELEASE_TAG'..."
169+
TAGS="$TAGS $GIT_RELEASE_TAG"
208170
209171
#Latest tag
210172
GIT_LAST_TAG=$(git tag --sort=v:refname | tail -n 1);
211173
echo "GIT_LAST_TAG=$GIT_LAST_TAG"
212174
if [ "$GIT_RELEASE_TAG" == "$GIT_LAST_TAG" ]; then
213175
echo "Tagging and uploading 'latest'..."
176+
TAGS="$TAGS latest"
214177
else
215178
echo "NOT uploading 'latest'..."
216179
fi
217180
else
218181
echo "NOT uploading '$GIT_RELEASE_TAG' nor 'latest'. Not a release!"
219182
fi
220183
221-
#Let's do it!
222-
EXT_DAEMONS="base ${DAEMONS}"
223-
for DAEMON in ${EXT_DAEMONS}; do
224-
if [ "$GIT_IS_BLEEDING_EDGE" != "" ]; then
225-
docker tag ${DAEMON}:_build ${DOCKER_USERNAME}/${DAEMON}:bleeding-edge;
226-
docker push ${DOCKER_USERNAME}/${DAEMON}:bleeding-edge;
227-
fi
228-
if [ "$GIT_RELEASE_TAG" != "" ]; then
229-
docker tag ${DAEMON}:_build ${DOCKER_USERNAME}/${DAEMON}:${PMACCT_VERSION};
230-
docker push ${DOCKER_USERNAME}/${DAEMON}:${PMACCT_VERSION};
231-
if [ "$GIT_RELEASE_TAG" == "$GIT_LAST_TAG" ]; then
232-
docker tag ${DAEMON}:_build ${DOCKER_USERNAME}/${DAEMON}:latest;
233-
docker push ${DOCKER_USERNAME}/${DAEMON}:latest;
234-
fi
235-
fi
236-
done
184+
#Summarize deduced tags
185+
echo "Deduced tags: $TAGS"
186+
echo "TAGS=$TAGS" >> $GITHUB_ENV
187+
188+
- name: Get Runner's IP Address
189+
run: |
190+
RUNNER_IP=$(hostname -I | awk '{print $1}')
191+
echo "RUNNER_IP=$RUNNER_IP" >> $GITHUB_ENV
192+
echo "Deduced RUNNER_IP: $RUNNER_IP"
193+
194+
- name: Spawn docker registry
195+
run: |
196+
echo "Instruct dockerd to trust $RUNNER_IP:5000 as an insecure registry..."
197+
sudo mkdir -p /etc/docker
198+
echo "{
199+
\"insecure-registries\": [\"http://$RUNNER_IP:5000\"]
200+
}" | sudo tee /etc/docker/daemon.json > /dev/null
201+
sudo systemctl restart docker
202+
echo "Starting temporary docker registry..."
203+
docker run -d -p 5000:5000 --name registry registry:2
204+
205+
- name: Build for platforms
206+
run: |
207+
echo "Building platforms: ${{ env.PLATFORMS }}..."
208+
echo "Got tags from previous step: $TAGS"
209+
cd docker && BUILD_REGISTRY=$RUNNER_IP:5000 PLATFORMS="${{env.PLATFORMS}}" V=1 make
210+
211+
- name: Docker (compose) smoke test
212+
run: |
213+
echo "Running smoke test using docker compose..."
214+
export DOCKER_OPTS="--insecure-registry $RUNNER_IP:5000"
215+
TAG=_build REPO=$RUNNER_IP:5000/ docker compose -f ci/smoke-test/docker-compose.yml up -d
216+
sleep 10
217+
echo "Check that all containers are up and running, without restarts ..."
218+
if [[ "$(docker inspect `docker ps -aq` | grep RestartCount | grep -v '\"RestartCount\": 0')" != "" ]]; then
219+
echo "Some containers restarted!" && docker inspect `docker ps -aq` && /bin/false
220+
fi
221+
echo "Stopping containers..."
222+
TAG=_build docker compose -f ci/smoke-test/docker-compose.yml down
223+
224+
- name: Tag and push to dockerhub
225+
if: ${{ github.event_name != 'pull_request' && vars.SKIP_DOCKERHUB_PUBLISH != 'true' && env.TAGS != '' }}
226+
env:
227+
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
228+
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
229+
run: |
230+
echo "Logging in...";
231+
echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USERNAME} --password-stdin
232+
echo "Publishing platforms(archs): ${{ env.PLATFORMS }}..."
233+
echo "Got tags from previous step: $TAGS"
234+
cd docker && BUILD_REGISTRY=$RUNNER_IP:5000 PUSH=${{secrets.DOCKER_USERNAME}} TAGS="${TAGS}" PLATFORMS="${{env.PLATFORMS}}" V=1 make

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,5 @@ test-framework/**/*.bak
6363
tests/**/*.bak
6464
test-framework/results/
6565

66+
#Docker stuff
67+
docker/.buildx_config.toml

ci/deps.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ mkdir -p /tmp
3535
cd /tmp
3636

3737
# Dependencies (not fulfilled by Dockerfile)
38-
git clone --depth 1 https://github.com/akheron/jansson
38+
git clone --depth 1 -b v2.14 https://github.com/akheron/jansson
3939
cd jansson ; rm -rf ./.git ; autoreconf -i ; ./configure --prefix=/usr/local/ ; make ; sudo make install ; cd ..
4040

41-
git clone --depth 1 https://github.com/edenhill/librdkafka
41+
git clone --depth 1 -b v2.6.1 https://github.com/confluentinc/librdkafka
4242
cd librdkafka ; rm -rf ./.git ; ./configure --prefix=/usr/local/ ; make ; sudo make install ; cd ..
4343

4444
# rabbitmq-c 0.14.0 depends on cmake 3.22 or greater
@@ -50,7 +50,7 @@ else
5050
cd rabbitmq-c-0.13.0 ; mkdir build ; cd build ; cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_INSTALL_LIBDIR=lib .. ; sudo cmake --build . --target install ; cd .. ; cd ..
5151
fi
5252

53-
git clone --depth 1 --recursive https://github.com/maxmind/libmaxminddb
53+
git clone --depth 1 -b 1.11.0 --recursive https://github.com/maxmind/libmaxminddb
5454
cd libmaxminddb ; rm -rf ./.git ; ./bootstrap ; ./configure --prefix=/usr/local/ ; make ; sudo make install ; cd ..
5555

5656
git clone --depth 1 -b 4.8-stable https://github.com/ntop/nDPI

ci/smoke-test/docker-compose.yml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,42 @@
1-
version: "3"
2-
31
services:
42
nfacctd:
5-
image: nfacctd:${TAG}
3+
image: ${REPO:-}nfacctd:${TAG}
64
volumes:
75
- ./etc/pmacct:/etc/pmacct
86
restart: on-failure
97

108
pmacctd:
11-
image: pmacctd:${TAG}
9+
image: ${REPO:-}pmacctd:${TAG}
1210
volumes:
1311
- ./etc/pmacct:/etc/pmacct
1412
restart: on-failure
1513

1614
pmbgpd:
17-
image: pmbgpd:${TAG}
15+
image: ${REPO:-}pmbgpd:${TAG}
1816
volumes:
1917
- ./etc/pmacct:/etc/pmacct
2018
restart: on-failure
2119

2220
pmbmpd:
23-
image: pmbmpd:${TAG}
21+
image: ${REPO:-}pmbmpd:${TAG}
2422
volumes:
2523
- ./etc/pmacct:/etc/pmacct
2624
restart: on-failure
2725

2826
pmtelemetryd:
29-
image: pmtelemetryd:${TAG}
27+
image: ${REPO:-}pmtelemetryd:${TAG}
3028
volumes:
3129
- ./etc/pmacct:/etc/pmacct
3230
restart: on-failure
3331

3432
sfacctd:
35-
image: sfacctd:${TAG}
33+
image: ${REPO:-}sfacctd:${TAG}
3634
volumes:
3735
- ./etc/pmacct:/etc/pmacct
3836
restart: on-failure
3937

4038
uacctd:
41-
image: uacctd:${TAG}
39+
image: ${REPO:-}uacctd:${TAG}
4240
volumes:
4341
- ./etc/pmacct:/etc/pmacct
4442
restart: on-failure

docker/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!Makefile

docker/Makefile

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
SHELL := /bin/bash
2+
.SHELLFLAGS := -e -c
3+
4+
PLATFORMS ?= linux/amd64
5+
DAEMONS ?= pmacctd nfacctd sfacctd uacctd pmbgpd pmbmpd pmtelemetryd
6+
DEPS_DONT_CHECK_CERTIFICATE ?=
7+
N_WORKERS ?= 2
8+
PROGRESS ?= --progress=plain
9+
MEMORY ?= 8g
10+
TAGS ?=
11+
BUILD_REGISTRY ?=
12+
LOAD ?=
13+
PUSH ?=
14+
15+
ifneq ($(strip $(PUSH)),)
16+
PUSH_ARG = --push
17+
endif
18+
19+
ifneq ($(strip $(BUILD_REGISTRY)),)
20+
BUILD_REGISTRY_REPO=$(BUILD_REGISTRY)/
21+
BUILD_REGISTRY_PUSH=--push
22+
else
23+
LOAD=--load
24+
endif
25+
26+
ifeq ($(V),1)
27+
QUIET =
28+
else
29+
QUIET = @
30+
endif
31+
32+
all: build
33+
34+
build: __dump_env __builder_setup build_base build_daemons
35+
36+
__dump_env:
37+
$(QUIET) echo "Env:"
38+
$(QUIET) echo " PLATFORMS: $(PLATFORMS)"
39+
$(QUIET) echo " DAEMONS: $(DAEMONS)"
40+
$(QUIET) echo " DEPS_DONT_CHECK_CERTIFICATE: $(DEPS_DONT_CHECK_CERTIFICATE)"
41+
$(QUIET) echo " N_WORKERS: $(N_WORKERS)"
42+
$(QUIET) echo " MEMORY: $(MEMORY)"
43+
$(QUIET) echo " BUILD_REGISTRY: $(BUILD_REGISTRY)"
44+
$(QUIET) echo " PUSH: $(PUSH)"
45+
$(QUIET) echo " TAGS: $(TAGS)"
46+
$(QUIET) echo " V: $(V)"
47+
$(QUIET) echo " ---"
48+
$(QUIET) echo " BUILD_REGISTRY_REPO: $(BUILD_REGISTRY_REPO)"
49+
$(QUIET) echo " PUSH_ARG: $(PUSH_ARG)"
50+
$(QUIET) echo " LOAD: $(LOAD)"
51+
$(QUIET) echo " QUIET: $(QUIET)"
52+
53+
__builder_setup:
54+
$(QUIET) echo "Installing QEMU-based multi-arch builder..."
55+
$(QUIET) if [[ "$(BUILD_REGISTRY)" != "" ]]; then \
56+
if [ -z "$$(docker buildx ls | grep xbuilder)" ]; then \
57+
echo "" > .buildx_config.toml; \
58+
echo '[registry."$(BUILD_REGISTRY)"]' >> .buildx_config.toml; \
59+
echo ' http = true' >> .buildx_config.toml; \
60+
docker buildx create --name xbuilder --driver docker-container --config .buildx_config.toml --use; \
61+
fi; \
62+
docker buildx use xbuilder; \
63+
else \
64+
echo "Using default buildx builder..."; \
65+
fi; \
66+
docker run --privileged multiarch/qemu-user-static --reset -p yes
67+
build_base:
68+
$(QUIET) echo "Building base container..."
69+
$(QUIET) TAGS_BASE=""; for TAG in $(TAGS); do TAGS_BASE="$$TAGS_BASE -t $(PUSH)/base:$${TAG} "; done; \
70+
docker buildx build $(PROGRESS) --memory $(MEMORY) --platform $(PLATFORMS) -t $(BUILD_REGISTRY_REPO)base:_build $(LOAD) $(BUILD_REGISTRY_PUSH) --build-arg NUM_WORKERS=$(N_WORKERS) --build-arg DEPS_DONT_CHECK_CERTIFICATE=$(DEPS_DONT_CHECK_CERTIFICATE) -f base/Dockerfile .. ; \
71+
if [ -n "$(PUSH)" ]; then \
72+
docker buildx build $(PROGRESS) --memory $(MEMORY) --platform $(PLATFORMS) $${TAGS_BASE} $(PUSH_ARG) --build-arg NUM_WORKERS=$(N_WORKERS) --build-arg DEPS_DONT_CHECK_CERTIFICATE=$(DEPS_DONT_CHECK_CERTIFICATE) -f base/Dockerfile .. ; \
73+
fi
74+
75+
build_daemons:
76+
$(QUIET) for DAEMON in $(DAEMONS); do \
77+
TAGS_DAEMON=""; for TAG in $(TAGS); do TAGS_DAEMON="$$TAGS_DAEMON -t $(PUSH)/$${DAEMON}:$${TAG} "; done; \
78+
echo "Building '$${DAEMON}'"; \
79+
docker buildx build $(PROGRESS) --memory $(MEMORY) --platform $(PLATFORMS) -t $(BUILD_REGISTRY_REPO)$${DAEMON}:_build $(LOAD) $(BUILD_REGISTRY_PUSH) --build-arg BUILD_REGISTRY=$(BUILD_REGISTRY) -f $${DAEMON}/Dockerfile .. ; \
80+
if [ -n "$(PUSH)" ]; then \
81+
docker buildx build $(PROGRESS) --memory $(MEMORY) --platform $(PLATFORMS) $${TAGS_DAEMON} $(PUSH_ARG) --build-arg BUILD_REGISTRY=$(BUILD_REGISTRY) -f $${DAEMON}/Dockerfile .. ; \
82+
fi \
83+
done
84+
85+
clean:
86+
$(QUIET) docker run --privileged multiarch/qemu-user-static --reset
87+
$(QUIET) docker buildx rm xbuilder

0 commit comments

Comments
 (0)