Skip to content

Commit

Permalink
CRIU Alpine Dockerimage for Multi-stage Builds
Browse files Browse the repository at this point in the history
  • Loading branch information
avmnu-sng committed Jan 9, 2024
1 parent 5f8b850 commit 37a6013
Show file tree
Hide file tree
Showing 5 changed files with 249 additions and 2 deletions.
95 changes: 95 additions & 0 deletions .github/workflows/build-and-push.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: build-and-push

on:
pull_request:
push:
branches:
- main

env:
PLATFORM: "linux/amd64"

jobs:
docker:
runs-on: ubuntu-latest

strategy:
matrix:
base:
- "alpine:3.18.5@sha256:d695c3de6fcd8cfe3a6222b0358425d40adfd129a8a47c3416faff1a8aece389"
criu:
- "3.19"
nftables:
- "with-nftables"
- "without-nftables"

steps:
- name: Checkout
uses: actions/checkout@v4

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

- name: Get base image version
id: base-image-version
run: |
base_image_version=$(echo ${{ matrix.base }} | cut -d@ -f1 | tr ':' '-')
tag="avmnusng/criu-${{ matrix.criu }}-${{ matrix.nftables }}:${base_image_version}"
echo "TAG=${tag}" >> $GITHUB_ENV
echo "TAG_TEST=${tag}-test" >> $GITHUB_ENV
- name: Build
uses: docker/build-push-action@v5
with:
context: "."
file: ${{ matrix.nftables }}.Dockerfile
platforms: ${{ env.PLATFORM }}
load: true
tags: ${{ env.TAG_TEST }}
build-args: |
PLATFORM=${{ env.PLATFORM }}
BASE=${{ matrix.base }}
CRIU_VERSION=${{ matrix.criu }}
- name: Test
run: docker run --rm --privileged ${{ env.TAG_TEST }} criu check

- name: Test multi-stage build
run: |
cat <<EOF >> ${{ matrix.nftables }}-multi-stage.Dockerfile
FROM --platform=${{ env.PLATFORM }} ${{ matrix.base }}
COPY --from=${{ env.TAG_TEST }} /criu/ /
EOF
if [[ $? != 0 ]]; then
exit 0
fi
docker build \
-t ${{ matrix.nftables }}-multi-stage:test \
-f ${{ matrix.nftables }}-multi-stage.Dockerfile \
. && \
docker run --rm --privileged ${{ matrix.nftables }}-multi-stage:test criu check
- name: Login to Docker Hub
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
if: github.event_name == 'push'
uses: docker/build-push-action@v5
with:
context: "."
file: ${{ matrix.nftables }}.Dockerfile
platforms: ${{ env.PLATFORM }}
push: true
tags: ${{ env.TAG }}
build-args: |
PLATFORM=${{ env.PLATFORM }}
BASE=${{ matrix.base }}
CRIU_VERSION=${{ matrix.criu }}
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
# criu-alpine
CRIU Dockerimage for multi-stage builds
## CRIU Alpine

Use this dockerimage to add [criu](https://github.com/checkpoint-restore/criu) as
part of multi-stage build. To use in multistage build copy all the contents from
the `/criu` directory to `/` (root) directory.

Ensure to use same alpine image for the final stage, i.e., if we use `alpine:3.18.5`
with digest `sha256:d695c3de6fcd8cfe3a6222b0358425d40adfd129a8a47c3416faff1a8aece389`,
then:

```dockerfile
FROM --platform=amd64 alpine:3.18.5@sha256:d695c3de6fcd8cfe3a6222b0358425d40adfd129a8a47c3416faff1a8aece389

COPY --from=criu-3.19-with-nftables:alpine-3.18.5 /criu/ /
```
57 changes: 57 additions & 0 deletions multi-stage-setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env python3

from pathlib import Path
from shutil import copy2
from subprocess import run
from sys import exit

CRIU_ROOT = '/criu'
CRIU_BIN_DIR = f'{CRIU_ROOT}/usr/bin'


def setup_criu_root():
Path(CRIU_ROOT).mkdir(parents=True, exist_ok=False)
Path(CRIU_BIN_DIR).mkdir(parents=True, exist_ok=False)

if not run(f'cp `which criu` {CRIU_BIN_DIR}', shell=True).returncode == 0:
exit(1)


def copy_dep(dep):
dep_dir = str(Path(CRIU_ROOT).joinpath(Path(dep).parent.relative_to('/')))
Path(dep_dir).mkdir(parents=True, exist_ok=True)

copy2(dep, dep_dir)


if __name__ == '__main__':
setup_criu_root()

res = run('ldd `which criu`', capture_output=True, shell=True)
if not res.returncode == 0:
exit(1)

deps = res.stdout.decode().strip().split("\n")

for dep in deps:
parts = dep.strip().split(' => ')
if len(parts) not in (1, 2):
exit(1)

part1 = None
part2 = None

if len(parts) == 1:
part1 = parts[0].split(' (0x')[0]
part2 = part1
else:
part2 = parts[1].split(' (0x')[0]
part1 = str(Path(part2).parent.joinpath(parts[0]))

if not part1 or not part2:
exit(1)

copy_dep(part1)

if part1 != part2:
copy_dep(part2)
42 changes: 42 additions & 0 deletions with-nftables.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
ARG PLATFORM
ARG BASE

FROM --platform=$PLATFORM $BASE

ARG CRIU_VERSION

RUN apk --update --no-cache add \
bash \
build-base \
coreutils \
procps \
gcc \
git \
gnutls-dev \
libaio-dev \
libcap-dev \
libnet-dev \
libnl3-dev \
nftables \
nftables-dev \
pkgconfig \
protobuf-c-dev \
protobuf-dev \
py3-pip \
py3-protobuf \
python3 \
libcap-utils \
libdrm-dev \
util-linux

WORKDIR /tmp

RUN wget "http://github.com/checkpoint-restore/criu/archive/v${CRIU_VERSION}/criu-${CRIU_VERSION}.tar.gz" && \
tar -xzf "criu-${CRIU_VERSION}.tar.gz" && \
cd "criu-${CRIU_VERSION}" && \
make -j $(nproc) install-criu

COPY multi-stage-setup.py multi-stage-setup.py

RUN chmod +x multi-stage-setup.py && \
./multi-stage-setup.py
40 changes: 40 additions & 0 deletions without-nftables.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
ARG PLATFORM
ARG BASE

FROM --platform=$PLATFORM $BASE

ARG CRIU_VERSION

RUN apk --update --no-cache add \
bash \
build-base \
coreutils \
procps \
gcc \
git \
gnutls-dev \
libaio-dev \
libcap-dev \
libnet-dev \
libnl3-dev \
pkgconfig \
protobuf-c-dev \
protobuf-dev \
py3-pip \
py3-protobuf \
python3 \
libcap-utils \
libdrm-dev \
util-linux

WORKDIR /tmp

RUN wget "http://github.com/checkpoint-restore/criu/archive/v${CRIU_VERSION}/criu-${CRIU_VERSION}.tar.gz" && \
tar -xzf "criu-${CRIU_VERSION}.tar.gz" && \
cd "criu-${CRIU_VERSION}" && \
make -j $(nproc) install-criu

COPY multi-stage-setup.py multi-stage-setup.py

RUN chmod +x multi-stage-setup.py && \
./multi-stage-setup.py

0 comments on commit 37a6013

Please sign in to comment.