Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/actions/build/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "Build & publish images"
description: "Builds images and pushes them to ghcr.io"

inputs:
context:
description: “Context directory for the build”
required: true
image_name:
description: "Full name (incl. tag)"
required: true

runs:
using: "composite"
steps:
- name: "Checkout"
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
with:
platforms: 'arm64,arm'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v4
with:
context: ${inputs.context}
file: ${inputs.context}/Dockerfile
no-cache: true
platforms: linux/amd64,linux/arm,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ inputs.image_name }}


35 changes: 11 additions & 24 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,20 @@ on:
branches:
- main
jobs:
publish-test-base-image:
build-and-publish-all-images:
runs-on: ubuntu-latest
env:
IMAGE_NAME: ghcr.io/crac/test-base
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- uses: ./.github/actions/build
with:
platforms: 'arm64,arm'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
context: test-base
image_name: ghcr.io/crac/test-base
- uses: ./.github/actions/build
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v4
context: jdk
image_name: ghcr.io/crac/jdk
- uses: ./.github/actions/build
with:
context: test-base
file: test-base/Dockerfile
no-cache: true
platforms: linux/amd64,linux/arm,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ env.IMAGE_NAME }}
context: example-jetty
image_name: ghcr.io/crac/example-jetty


13 changes: 13 additions & 0 deletions example-jetty/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ARG BASEIMG=ghcr.io/crac/jdk

FROM $BASEIMG AS builder
RUN apt-get update && apt-get install -y git maven
RUN cd /tmp && git clone https://github.com/CRaC/example-jetty
RUN cd /tmp/example-jetty && mvn package

FROM $BASEIMG
RUN mkdir /opt/example-jetty/
COPY --from=builder /tmp/example-jetty/target/dependency /opt/example-jetty/dependency
COPY --from=builder /tmp/example-jetty/target/example-jetty*.jar /opt/example-jetty/example-jetty.jar
CMD [ "/usr/bin/java", "-XX:CRaCCheckpointTo=/cr", "-jar", "/opt/example-jetty/example-jetty.jar" ]

31 changes: 31 additions & 0 deletions jdk/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
ARG TAG=17-crac+5
ARG JDK=openjdk-${TAG}_linux-x64

FROM ubuntu:latest AS builder
# We are not using Docker ADD <remote src> command as this does not cache the file
RUN apt-get update && apt-get install -y wget
ARG TAG
ARG JDK
ARG CHECKSUM=bf4405578cd445e5c6501c76cf72aac555fc76dec35a41a5219e4511c099e1da
RUN cd /opt && wget -nv "https://github.com/CRaC/openjdk-builds/releases/download/$TAG/$JDK.tar.gz"
RUN echo "$CHECKSUM /opt/$JDK.tar.gz" > /opt/checksum
RUN sha256sum --check /opt/checksum
RUN cd /opt && tar xzf $JDK.tar.gz

FROM ubuntu:latest
ARG JDK
COPY --from=builder /opt/$JDK /opt/$JDK
# Symlink on well-known place is useful for exec form of CMD
RUN ln -s /opt/$JDK/bin/java /usr/bin/java
RUN mkdir /cr && chmod a+rwx /cr
ADD entrypoint.sh /opt/entrypoint.sh
ADD checkpoint.sh /opt/checkpoint.sh
ADD restore.sh /opt/restore.sh
ENTRYPOINT [ "/opt/entrypoint.sh" ]
CMD [ "bash" ]
# Unprivileged restore does not work ATM so we'll use root user
#RUN useradd -m -u 1000 user
#USER user
ENV JAVA_HOME /opt/$JDK
ENV PATH $JAVA_HOME/bin:/opt:$PATH

21 changes: 21 additions & 0 deletions jdk/checkpoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -o pipefail

if ! echo 1000 | tee /proc/sys/kernel/ns_last_pid > /dev/null 2>&1 ; then
echo "This container is unprivileged, cannot perform checkpoint. Use docker run --privileged ..." >&2
exit 1;
fi

PIDS=$(jps -v | grep -e '-XX:CRaCCheckpointTo=' | cut -f 1 -d ' ')
if [ -z "$PIDS" ]; then
echo "No processes to checkpoint." >&2
exit 1;
fi
for PID in $PIDS; do
IMAGEDIR=$(jps -v | sed -n 's/^'$PID'.*-XX:CRaCCheckpointTo=\([^ \t]*\).*/\1/p')
if ! mount | grep -e " on $IMAGEDIR " > /dev/null; then
echo "WARNING: Image directory $IMAGEDIR does not seem to be bound outside container. Have you forgot -v /path/to/cr:$IMAGEDIR ?" >&2
fi
jcmd $PID JDK.checkpoint
done
29 changes: 29 additions & 0 deletions jdk/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

set -o pipefail

if !(echo "$@" | grep -e '-XX:CRaCRestoreFrom\|restore.sh' > /dev/null) || [ -n "$CHECKPOINT" ]; then
# This is the run that's going to be checkpointed

# This makes sure that the new process is started with high enough PID
# - otherwise a restore without --privileged wouldn't succeed
if ! echo ${MIN_PID:-1000} | tee /proc/sys/kernel/ns_last_pid > /dev/null 2>&1 ; then
echo "WARNING: This container is unprivileged, cannot perform checkpoint. Use docker run --privileged ..." >&2
fi

if echo "$@" | grep -e "-XX:CRaCCheckpointTo" > /dev/null; then
IMAGEDIR=$(echo "$@" | sed -n 's/.*-XX:CRaCCheckpointTo=\([^ \t]*\).*/\1/p')
if ! mount | grep -e " on $IMAGEDIR " > /dev/null; then
echo "WARNING: Image directory $IMAGEDIR does not seem to be bound outside container. Have you forgot -v /path/to/cr:$IMAGEDIR ?" >&2
fi

if [ "$1" = "/bin/sh" -a "$2" = "-c" ]; then
echo "It appears that CMD has a shell-form rather than exec-form. This could result in this container exiting before the image directory is fully written." >&2
echo "For more information about shell-form vs. exec-form please see https://docs.docker.com/engine/reference/builder/#cmd" >&2
exit 1
fi
fi
fi

# We execute right into the process as staying in shell script would cause trouble with propagating signals
exec "$@"
33 changes: 33 additions & 0 deletions jdk/restore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

restore() {
echo "Restoring from $1 ..."
IMAGEDIR=$1
shift
exec /usr/bin/java -XX:CRaCRestoreFrom=$IMAGEDIR "$@"
}

if [ -n "$IMAGEDIR" ]; then
if [ ! -d "$IMAGEDIR" ]; then
echo "'$IMAGEDIR' is not a directory, cannot restore." >&2
exit 1
elif [ ! -f "$IMAGEDIR/cppath" ]; then
echo "Directory $IMAGEDIR does not contain file 'cppath', cannot restore." >&2
exit 1
fi
restore $IMAGEDIR "$@"
fi

CANDIDATES=$(mount | grep /dev/mapper/vgubuntu-root | grep -v -e 'on /etc' | sed -e 's/.* on \(\/[^ ]*\) type.*/\1/')
if [ -z "$CANDIDATES" ]; then
echo "No volumes mounted for C/R found" >&2
exit 1;
fi
for DIR in $CANDIDATES; do
if [ -f $DIR/cppath ]; then
restore $DIR "$@"
fi
done

echo "Did not find 'cppath' in any of the available mounts; cannot restore." >&2
exit 1