Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Commit

Permalink
Make a new Kubernetes friendly Docker image (#1499)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
NicolasMassart authored Jun 7, 2019
1 parent 741ebfc commit d4bbeae
Show file tree
Hide file tree
Showing 11 changed files with 356 additions and 23 deletions.
13 changes: 12 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
.github
.gradle
.idea
.vertx
build
build
kubernetes
Dockerfile

#Exclude doc related resources
docs
mkdocs.yml
readthedocs.yml
*.md

Jenkins*
5 changes: 0 additions & 5 deletions .env

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ tmp/
build/
out/
site/
/kubernetes/reports/
/kubernetes/pantheon-*.tar.gz
90 changes: 73 additions & 17 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -174,29 +174,85 @@ try {
}
}
}

if (env.BRANCH_NAME == "master") {
node {
checkout scm
unstash 'distTarBall'
docker.image(docker_image_dind).withRun('--privileged') { d ->
docker.image(docker_image).inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
stage('build image') {
sh "cd docker && cp ../build/distributions/pantheon-*.tar.gz ."
pantheon = docker.build("pegasyseng/pantheon:develop", "docker")
def registry = 'https://registry.hub.docker.com'
def userAccount = 'dockerhub-pegasysengci'
def imageRepos = 'pegasyseng'
def imageTag = 'develop'
parallel KubernetesDockerImage: {
def stage_name = 'Kubernetes Docker image node: '
def image = imageRepos + '/pantheon-kubernetes:' + imageTag
def kubernetes_folder = 'kubernetes'
def kubernetes_image_build_script = kubernetes_folder + '/build_image.sh'
def version_property_file = 'gradle.properties'
def reports_folder = kubernetes_folder + '/reports'
def dockerfile = kubernetes_folder + '/Dockerfile'
node {
checkout scm
unstash 'distTarBall'
docker.image(build_image).inside() {
stage(stage_name + 'Dockerfile lint') {
sh "docker run --rm -i hadolint/hadolint < ${dockerfile}"
}
stage(stage_name + 'Build image') {
sh "${kubernetes_image_build_script} '${image}'"
}
stage(stage_name + "Test image labels") {
shortCommit = sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%h'").trim()
version = sh(returnStdout: true, script: "grep -oE \"version=(.*)\" ${version_property_file} | cut -d= -f2").trim()
sh "docker image inspect \
--format='{{index .Config.Labels \"org.label-schema.vcs-ref\"}}' \
${image} \
| grep ${shortCommit}"
sh "docker image inspect \
--format='{{index .Config.Labels \"org.label-schema.version\"}}' \
${image} \
| grep ${version}"
}
try {
stage('test image') {
sh "apk add bash"
sh "mkdir -p docker/reports"
sh "cd docker && bash test.sh pegasyseng/pantheon:develop"
stage(stage_name + 'Test image') {
sh "mkdir -p ${reports_folder}"
sh "cd ${kubernetes_folder} && bash test.sh ${image}"
}
} finally {
junit 'docker/reports/*.xml'
sh "rm -rf docker/reports"
junit "${reports_folder}/*.xml"
sh "rm -rf ${reports_folder}"
}
stage('push image') {
docker.withRegistry('https://registry.hub.docker.com', 'dockerhub-pegasysengci') {
pantheon.push()
stage(stage_name + 'Push image') {
docker.withRegistry(registry, userAccount) {
docker.image(image).push()
}
}
}
}
},
DockerImage: {
def stage_name = 'Docker image node: '
def image = imageRepos + '/pantheon:' + imageTag
node {
checkout scm
unstash 'distTarBall'
docker.image(docker_image_dind).withRun('--privileged') { d ->
docker.image(docker_image).inside("-e DOCKER_HOST=tcp://docker:2375 --link ${d.id}:docker") {
stage(stage_name + 'build image') {
sh "cd docker && cp ../build/distributions/pantheon-*.tar.gz ."
pantheon = docker.build(image, "docker")
}
try {
stage('test image') {
sh "apk add bash"
sh "mkdir -p docker/reports"
sh "cd docker && bash test.sh ${image}"
}
} finally {
junit 'docker/reports/*.xml'
sh "rm -rf docker/reports"
}
stage(stage_name + 'push image') {
docker.withRegistry(registry, userAccount) {
pantheon.push()
}
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions kubernetes/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"
39 changes: 39 additions & 0 deletions kubernetes/build_image.sh
Original file line number Diff line number Diff line change
@@ -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}
24 changes: 24 additions & 0 deletions kubernetes/test.sh
Original file line number Diff line number Diff line change
@@ -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
40 changes: 40 additions & 0 deletions kubernetes/tests/01/goss.yaml
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions kubernetes/tests/01/goss_wait.yaml
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit d4bbeae

Please sign in to comment.