mirror of https://github.com/hyperledger/besu
Make a new Kubernetes friendly Docker image (#1499)
The following PIE-1598 subtasks are fixed: fixes PIE-1600 remove entrypoint script fixes PIE-1601 investigate Dockerfile best practices including : - naming - multi step build - comments - labels - build args - entrypoint - minimalism fixes PIE-1604 rewrite Dockerfile according to best practices provide a sample build command that can be used as-is or as an example. Added contents to .dockerignore to make the intermediate build image smaller. Remove .env file that was supposed to be used long ago for a docker quickstart and that we forgot to remove ans is useless today. add jenkins pipeline to test the docker image build Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
6003ff92a2
commit
48e771b3a6
@ -1,4 +1,15 @@ |
|||||||
|
.github |
||||||
.gradle |
.gradle |
||||||
.idea |
.idea |
||||||
.vertx |
.vertx |
||||||
build |
build |
||||||
|
kubernetes |
||||||
|
Dockerfile |
||||||
|
|
||||||
|
#Exclude doc related resources |
||||||
|
docs |
||||||
|
mkdocs.yml |
||||||
|
readthedocs.yml |
||||||
|
*.md |
||||||
|
|
||||||
|
Jenkins* |
@ -1,5 +0,0 @@ |
|||||||
#Default env variables for docker compose quickstart |
|
||||||
#defaults are empty values |
|
||||||
RPC_PORT_MAPPING= |
|
||||||
WS_PORT_MAPPING= |
|
||||||
EXPLORER_PORT_MAPPING= |
|
@ -0,0 +1,36 @@ |
|||||||
|
# extract image stage |
||||||
|
# extractin here reduces the number of layers in the final image |
||||||
|
FROM alpine:3.9 AS extract-stage |
||||||
|
# Copy Pantheon binaries from previous jenkins artefact step |
||||||
|
# or from the result of ./gradlew distTar |
||||||
|
# and lett ADD unpack them |
||||||
|
ADD pantheon-*.tar.gz /tmp/ |
||||||
|
|
||||||
|
# Run image stage |
||||||
|
# Use openJDK JRE only for running pantheon |
||||||
|
FROM openjdk:11.0.2-jre-slim-stretch |
||||||
|
# Copy extracted binaries from the previous step image |
||||||
|
COPY --from=extract-stage /tmp/pantheon* /opt/pantheon |
||||||
|
WORKDIR /opt/pantheon |
||||||
|
# Expose services ports |
||||||
|
# 8545 HTTP JSON-RPC |
||||||
|
# 8546 WS JSON-RPC |
||||||
|
# 8547 HTTP GraphQL |
||||||
|
# 30303 P2P |
||||||
|
EXPOSE 8545 8546 8547 30303 |
||||||
|
ENTRYPOINT ["/opt/pantheon/bin/pantheon"] |
||||||
|
# Build-time metadata as defined at http://label-schema.org |
||||||
|
# Use the build_image.sh script in the kubernetes directory of this project to |
||||||
|
# easily build this image or as an example of how to inject build parameters. |
||||||
|
ARG BUILD_DATE |
||||||
|
ARG VCS_REF |
||||||
|
ARG VERSION |
||||||
|
LABEL org.label-schema.build-date=$BUILD_DATE \ |
||||||
|
org.label-schema.name="Pantheon" \ |
||||||
|
org.label-schema.description="Enterprise Ethereum client" \ |
||||||
|
org.label-schema.url="https://docs.pantheon.pegasys.tech/" \ |
||||||
|
org.label-schema.vcs-ref=$VCS_REF \ |
||||||
|
org.label-schema.vcs-url="https://github.com/PegaSysEng/pantheon.git" \ |
||||||
|
org.label-schema.vendor="Pegasys" \ |
||||||
|
org.label-schema.version=$VERSION \ |
||||||
|
org.label-schema.schema-version="1.0" |
@ -0,0 +1,39 @@ |
|||||||
|
#!/bin/sh -e |
||||||
|
# This script presents a sample way to build Pantheon Docker image |
||||||
|
# with automatic build arguments from the current build workspace. |
||||||
|
# It must be started from the same path as where the Dockerfile is located. |
||||||
|
# you have to pass the imnage tag as an argument like for instance : |
||||||
|
# build_image.sh "pegasyseng/pantheon-kubernetes:develop" |
||||||
|
|
||||||
|
CONTEXT_FOLDER=kubernetes/ |
||||||
|
PANTHEON_BUILD_SOURCE='build/distributions/pantheon-*.tar.gz' |
||||||
|
|
||||||
|
# Checking that you passed the tag for the image to be build |
||||||
|
if [ -z "$1" ] |
||||||
|
then |
||||||
|
me=`basename "$0"` |
||||||
|
echo "No image tag argument supplied to ${me}" |
||||||
|
echo "ex.: ${me} \"pegasyseng/pantheon-kubernetes:develop\"" |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
# looking for the distribution archive, either form CI step that builds form this |
||||||
|
# workspace sources but with multiple test steps first |
||||||
|
# or it builds it if you don't have one as you are probably |
||||||
|
# not in a CI step. |
||||||
|
if ls ${PANTHEON_BUILD_SOURCE} 1> /dev/null 2>&1; then |
||||||
|
cp ${PANTHEON_BUILD_SOURCE} ${CONTEXT_FOLDER} |
||||||
|
else |
||||||
|
echo "No pantheon-*.tar.gz archive found." |
||||||
|
echo "You are probably not running this from CI so running './gradlew distTar' first to have a local build" |
||||||
|
./gradlew distTar |
||||||
|
cp ${PANTHEON_BUILD_SOURCE} ${CONTEXT_FOLDER} |
||||||
|
fi |
||||||
|
|
||||||
|
# Builds docker image with tags matching the info form this current workspace |
||||||
|
docker build \ |
||||||
|
-t "$1" \ |
||||||
|
--build-arg BUILD_DATE="`date`" \ |
||||||
|
--build-arg VCS_REF="`git show -s --format=%h`" \ |
||||||
|
--build-arg VERSION="`grep -oE "version=(.*)" gradle.properties | cut -d= -f2`" \ |
||||||
|
${CONTEXT_FOLDER} |
@ -0,0 +1,24 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
export GOSS_PATH=tests/goss-linux-amd64 |
||||||
|
export GOSS_OPTS="$GOSS_OPTS --format junit" |
||||||
|
export GOSS_FILES_STRATEGY=cp |
||||||
|
DOCKER_IMAGE=$1 |
||||||
|
|
||||||
|
i=0 |
||||||
|
|
||||||
|
# Test for normal startup with ports opened |
||||||
|
GOSS_FILES_PATH=tests/01 \ |
||||||
|
bash tests/dgoss \ |
||||||
|
run $DOCKER_IMAGE \ |
||||||
|
--network=dev \ |
||||||
|
--p2p-host=0.0.0.0 \ |
||||||
|
--rpc-http-enabled \ |
||||||
|
--rpc-http-host=0.0.0.0 \ |
||||||
|
--rpc-ws-enabled \ |
||||||
|
--rpc-ws-host=0.0.0.0 \ |
||||||
|
--graphql-http-enabled \ |
||||||
|
--graphql-http-host=0.0.0.0 \ |
||||||
|
> ./reports/01.xml || i=`expr $i + 1` |
||||||
|
|
||||||
|
exit $i |
@ -0,0 +1,40 @@ |
|||||||
|
file: |
||||||
|
/opt/pantheon/bin/pantheon: |
||||||
|
exists: true |
||||||
|
mode: "0755" |
||||||
|
owner: root |
||||||
|
group: root |
||||||
|
filetype: file |
||||||
|
contains: [] |
||||||
|
/opt/pantheon/database: |
||||||
|
exists: true |
||||||
|
mode: "0755" |
||||||
|
owner: root |
||||||
|
group: root |
||||||
|
filetype: directory |
||||||
|
contains: [] |
||||||
|
/opt/pantheon/key: |
||||||
|
exists: true |
||||||
|
mode: "0600" |
||||||
|
owner: root |
||||||
|
group: root |
||||||
|
filetype: file |
||||||
|
contains: [] |
||||||
|
port: |
||||||
|
tcp:8545: |
||||||
|
listening: true |
||||||
|
tcp:8546: |
||||||
|
listening: true |
||||||
|
tcp:8547: |
||||||
|
listening: true |
||||||
|
tcp:30303: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
||||||
|
udp:30303: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
||||||
|
process: |
||||||
|
java: |
||||||
|
running: true |
@ -0,0 +1,17 @@ |
|||||||
|
port: |
||||||
|
tcp:30303: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
||||||
|
tcp:8545: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
||||||
|
tcp:8546: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
||||||
|
tcp:8547: |
||||||
|
listening: true |
||||||
|
ip: |
||||||
|
- 0.0.0.0 |
@ -0,0 +1,113 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
set -e |
||||||
|
|
||||||
|
USAGE="USAGE: $(basename "$0") [run|edit] <docker_run_params>" |
||||||
|
GOSS_FILES_PATH="${GOSS_FILES_PATH:-.}" |
||||||
|
|
||||||
|
info() { |
||||||
|
echo -e "INFO: $*" >&2; |
||||||
|
} |
||||||
|
error() { |
||||||
|
echo -e "ERROR: $*" >&2; |
||||||
|
exit 1; |
||||||
|
} |
||||||
|
|
||||||
|
cleanup() { |
||||||
|
set +e |
||||||
|
{ kill "$log_pid" && wait "$log_pid"; } 2> /dev/null |
||||||
|
rm -rf "$tmp_dir" |
||||||
|
if [[ $id ]];then |
||||||
|
info "Deleting container" |
||||||
|
docker rm -vf "$id" > /dev/null |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
run(){ |
||||||
|
# Copy in goss |
||||||
|
cp "${GOSS_PATH}" "$tmp_dir/goss" |
||||||
|
chmod 755 "$tmp_dir/goss" |
||||||
|
[[ -e "${GOSS_FILES_PATH}/goss.yaml" ]] && cp "${GOSS_FILES_PATH}/goss.yaml" "$tmp_dir" |
||||||
|
[[ -e "${GOSS_FILES_PATH}/goss_wait.yaml" ]] && cp "${GOSS_FILES_PATH}/goss_wait.yaml" "$tmp_dir" |
||||||
|
[[ ! -z "${GOSS_VARS}" ]] && [[ -e "${GOSS_FILES_PATH}/${GOSS_VARS}" ]] && cp "${GOSS_FILES_PATH}/${GOSS_VARS}" "$tmp_dir" |
||||||
|
|
||||||
|
# Switch between mount or cp files strategy |
||||||
|
GOSS_FILES_STRATEGY=${GOSS_FILES_STRATEGY:="mount"} |
||||||
|
case "$GOSS_FILES_STRATEGY" in |
||||||
|
mount) |
||||||
|
info "Starting docker container" |
||||||
|
id=$(docker run -d -v "$tmp_dir:/goss:z" "${@:2}") |
||||||
|
docker logs -f "$id" > "$tmp_dir/docker_output.log" 2>&1 & |
||||||
|
;; |
||||||
|
cp) |
||||||
|
info "Creating docker container" |
||||||
|
id=$(docker create ${@:2}) |
||||||
|
info "Copy goss files into container" |
||||||
|
docker cp $tmp_dir/. $id:/goss |
||||||
|
info "Starting docker container" |
||||||
|
docker start $id > /dev/null |
||||||
|
;; |
||||||
|
*) error "Wrong goss files strategy used! Correct options are \"mount\" or \"cp\"." |
||||||
|
esac |
||||||
|
|
||||||
|
log_pid=$! |
||||||
|
info "Container ID: ${id:0:8}" |
||||||
|
} |
||||||
|
|
||||||
|
get_docker_file() { |
||||||
|
if docker exec "$id" sh -c "test -e $1" > /dev/null;then |
||||||
|
mkdir -p "${GOSS_FILES_PATH}" |
||||||
|
info "Copied '$1' from container to '${GOSS_FILES_PATH}'" |
||||||
|
docker cp "$id:$1" "${GOSS_FILES_PATH}" |
||||||
|
fi |
||||||
|
} |
||||||
|
|
||||||
|
# Main |
||||||
|
tmp_dir=$(mktemp -d /tmp/tmp.XXXXXXXXXX) |
||||||
|
chmod 777 "$tmp_dir" |
||||||
|
trap 'ret=$?;cleanup;exit $ret' EXIT |
||||||
|
|
||||||
|
GOSS_PATH="${GOSS_PATH:-$(which goss 2> /dev/null || true)}" |
||||||
|
[[ $GOSS_PATH ]] || { error "Couldn't find goss installation, please set GOSS_PATH to it"; } |
||||||
|
[[ ${GOSS_OPTS+x} ]] || GOSS_OPTS="--color --format documentation" |
||||||
|
[[ ${GOSS_WAIT_OPTS+x} ]] || GOSS_WAIT_OPTS="-r 30s -s 1s > /dev/null" |
||||||
|
GOSS_SLEEP=${GOSS_SLEEP:-0.2} |
||||||
|
|
||||||
|
case "$1" in |
||||||
|
run) |
||||||
|
run "$@" |
||||||
|
if [[ -e "${GOSS_FILES_PATH}/goss_wait.yaml" ]]; then |
||||||
|
info "Found goss_wait.yaml, waiting for it to pass before running tests" |
||||||
|
if [[ -z "${GOSS_VARS}" ]]; then |
||||||
|
if ! docker exec "$id" sh -c "/goss/goss -g /goss/goss_wait.yaml validate $GOSS_WAIT_OPTS"; then |
||||||
|
error "goss_wait.yaml never passed" |
||||||
|
fi |
||||||
|
else |
||||||
|
if ! docker exec "$id" sh -c "/goss/goss -g /goss/goss_wait.yaml --vars='/goss/${GOSS_VARS}' validate $GOSS_WAIT_OPTS"; then |
||||||
|
error "goss_wait.yaml never passed" |
||||||
|
fi |
||||||
|
fi |
||||||
|
fi |
||||||
|
[[ $GOSS_SLEEP ]] && { info "Sleeping for $GOSS_SLEEP"; sleep "$GOSS_SLEEP"; } |
||||||
|
# info "Container health" |
||||||
|
# if ! docker top $id; then |
||||||
|
# docker logs $id |
||||||
|
# fi |
||||||
|
info "Running Tests" |
||||||
|
if [[ -z "${GOSS_VARS}" ]]; then |
||||||
|
docker exec "$id" sh -c "/goss/goss -g /goss/goss.yaml validate $GOSS_OPTS" |
||||||
|
else |
||||||
|
docker exec "$id" sh -c "/goss/goss -g /goss/goss.yaml --vars='/goss/${GOSS_VARS}' validate $GOSS_OPTS" |
||||||
|
fi |
||||||
|
;; |
||||||
|
edit) |
||||||
|
run "$@" |
||||||
|
info "Run goss add/autoadd to add resources" |
||||||
|
docker exec -it "$id" sh -c 'cd /goss; PATH="/goss:$PATH" exec sh' |
||||||
|
get_docker_file "/goss/goss.yaml" |
||||||
|
get_docker_file "/goss/goss_wait.yaml" |
||||||
|
[[ ! -z "${GOSS_VARS}" ]] && get_docker_file "/goss/${GOSS_VARS}" |
||||||
|
;; |
||||||
|
*) |
||||||
|
error "$USAGE" |
||||||
|
esac |
Binary file not shown.
Loading…
Reference in new issue