Slide 1

Slide 1 text

Ship containers fast with GitLab CI Niclas Mietz    [email protected] solidnerd solidnerd 1

Slide 2

Slide 2 text

CI, CD, CD? 2 . 1

Slide 3

Slide 3 text

Continuous Integration Software development practice where code is integrated regularly through a process that includes building and testing of the sourcecode 2 . 2

Slide 4

Slide 4 text

Continuous Delivery Implies to the CI a process to releasing integrated code with manual approvements into targeted software environments 2 . 3

Slide 5

Slide 5 text

Continuous Deployment Implies to the CI a process to releasing integrated code automatically into targeted software environments 2 . 4

Slide 6

Slide 6 text

What is GitLab ? An alternative to git hostings like GitHub GitHub Enterprise Gitea and others ... https://about.gitlab.com/ 3 . 1

Slide 7

Slide 7 text

Why more ? OpenCore (Sources of Community and Enterprise Edition are available for everyone) Track uni ed issues Being able to do Code Reviews directly in the UI Build CI/CD Pipeline into a single UI Works awlessly with Container Ecosystem like Docker or Kubernetes Automatic website generation (Pages) Every 22nd a new release, with new innovations and xes An API for Automation 3 . 2

Slide 8

Slide 8 text

Official and Unoffical GitLab Images (of cial) (unof cial) https://hub.docker.com/r/gitlab/gitlab-ce/ https://hub.docker.com/r/sameersbn/gitlab/ Currently sameersbn/gitlab is more cloud native agnostic 3 . 3

Slide 9

Slide 9 text

sameersbn/gitlab 12M+ Docker Hub Pulls 5,3k Stars on GitHub 336 releases on GitHub 143 contributors Big active Community https://github.com/sameersbn/docker-gitlab 3 . 4

Slide 10

Slide 10 text

Deep Dive Into GitLab 4

Slide 11

Slide 11 text

GitLab Container Architecture (sameersbn/gitlab) Unicor n (GitLab Rails) Postgr eSQL Sidekiq (GitLab Rails) GitLab Shell GitLab W orkorse NGINX GitLab Pages SSH HTTP HTTPS TCP 8090 TCP 8181 TCP 80, 443 TCP 8080 TCP 5432 Redis TCP 8080 TCP 22 TCP 6379 GitLab Container 5

Slide 12

Slide 12 text

GitLab CI 6 . 1

Slide 13

Slide 13 text

GitLab CI Compoments .gitlab-ci.yml de nes how the pipeline for a project looks like GitLab Runner executes the jobs that are de ned in the .gitlab-ci.yml GitLab itself as coordinator 6 . 2

Slide 14

Slide 14 text

GitLab CI Architecture 6 . 3

Slide 15

Slide 15 text

GitLab Runner GitLab Runner could be an isolated machine or an isolated virtual machine that picks up builds through the coordinator API of GitLab CI Con guration of the runner is placed in a le that is called config.toml 6 . 4

Slide 16

Slide 16 text

Shared vs. Specific Shared runners can run jobs for every project that has enabled shared runner Speci c runners run only for speci c jobs, they need to be enabled 6 . 5

Slide 17

Slide 17 text

Executors Executors are a special avor of a Runner De nes how a runner executes his jobs from GitLab 7 . 1

Slide 18

Slide 18 text

Executor Flavors Shell Parallels VirtualBox SSH 7 . 2

Slide 19

Slide 19 text

Executor with Container Flavor Docker Docker Machine (w/ autoscaling) Kubernetes 7 . 3

Slide 20

Slide 20 text

Docker Executor Docker Executor has three different ways to work with the Docker Engine Normal Wormhole DinD (Docker in Docker) 7 . 4

Slide 21

Slide 21 text

Normal 7 . 5

Slide 22

Slide 22 text

Wormhole 7 . 6

Slide 23

Slide 23 text

DinD (Docker in Docker) 7 . 7

Slide 24

Slide 24 text

Sharing your Artifacts (Images) Docker Distribution The Docker toolset to pack, ship, store, and deliver content 8 . 1

Slide 25

Slide 25 text

Simple registry deployment 8 . 2

Slide 26

Slide 26 text

GitLab Registry Authentication Workflow 8 . 3

Slide 27

Slide 27 text

Demo 9 . 1

Slide 28

Slide 28 text

Goal 9 . 2

Slide 29

Slide 29 text

Goal with Kubernetes 9 . 3

Slide 30

Slide 30 text

Using different ways to build java images 10 . 1

Slide 31

Slide 31 text

Simple Docker Build FROM maven:3.5.0-jdk-8 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ARG MAVEN_OPTS="-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jM COPY pom.xml /usr/src/app RUN mvn verify clean --fail-never COPY . /usr/src/app RUN mvn package \ && mkdir -p /usr/jar \ && mv /usr/src/app/target/helloworld-0.0.1-SNAPSHOT.jar /usr/jar/app.jar \ && rm -rf /usr/src/app/target/ ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar", "/usr/jar/app.jar"] 10 . 2

Slide 32

Slide 32 text

Simple Docker Build (CI) stages: - docker build:docker-image: stage: docker image: docker:latest script: - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} - docker image build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} . - docker image push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} 10 . 3

Slide 33

Slide 33 text

Build Pattern (Build) # Dockerfile.build FROM maven:3.5.0-jdk-8 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ARG MAVEN_OPTS="-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jM COPY pom.xml /usr/src/app RUN mvn verify clean --fail-never # COPY now all sources COPY . /usr/src/app RUN mvn package 10 . 4

Slide 34

Slide 34 text

Build Pattern (Run) #Dockerfile.run FROM openjdk:8u131-jre-alpine COPY target/helloworld-0.0.1-SNAPSHOT.jar /app.jar EXPOSE 8080 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar"] CMD ["/app.jar"] 10 . 5

Slide 35

Slide 35 text

Build Pattern (CI) stages: - docker build:docker-image: stage: docker image: docker:latest script: - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} - docker image build -t ${CI_REGISTRY_IMAGE}/java-build-img -f Dockerfile.build . - docker container create --name ${CI_PROJECT_NAME}-java-build-cont ${CI_REGISTRY_IMAGE}/java-build-img - mkdir -p $(pwd)/target/ - docker container cp ${CI_PROJECT_NAME}-java-build-cont:/usr/src/app/target/helloworld-0.0.1-SNAPSHOT.jar $(pwd) - docker container rm -f ${CI_PROJECT_NAME}-java-build-cont - docker image build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} -f Dockerfile.ru - docker image push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} 10 . 6

Slide 36

Slide 36 text

Multistage Build FROM maven:3.5.0-jdk-8 as build RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ARG MAVEN_OPTS="-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jM COPY pom.xml /usr/src/app RUN mvn verify clean --fail-never # COPY now all sources COPY . /usr/src/app RUN mvn package FROM openjdk:8u131-jre-alpine COPY --from=build /usr/src/app/target/helloworld-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 10 . 7

Slide 37

Slide 37 text

Multistage Build (CI) stages: - docker build:docker-image: stage: docker image: docker:latest script: - docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY} - docker image build -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} . - docker image push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA:0:5} 10 . 8

Slide 38

Slide 38 text

Good Docker Images 11 . 1

Slide 39

Slide 39 text

Base Images Use a Base Image to controll your Packages in your Pipeline 11 . 2

Slide 40

Slide 40 text

Comparsion of Base Images image size centos:7 193MB ubuntu:16.04 118MB debian:stretch 100MB debian:strech-slim 55.3MB alpine:3.6 3.97MB bitnami/minideb 53.6MB 11 . 3

Slide 41

Slide 41 text

 1. Tags 2. Labels 3. Digest 11 . 4

Slide 42

Slide 42 text

Tags Using tags to determine which image will be used Pointing to a speci cy image that will be used to run the container 11 . 5

Slide 43

Slide 43 text

Tags docker container -it --rm run alpine docker container -it --rm run alpine:latest docker container -it --rm run alpine:3.7 docker container -it --rm run alpine:3.8 11 . 6

Slide 44

Slide 44 text

Combine Tags with CI System (GitLab CI) docker: stage: build image: docker:latest script: - docker image build -t $CI_REGISTRY_IMAGE -t $CI_REGISTRY_IMAGE:$(git rev-parse --short HEAD) . - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY - docker push $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:$(git rev-parse --short HEAD) 11 . 7

Slide 45

Slide 45 text

Combine Tags with CI System (GitLab CI) docker: stage: build image: docker:latest script: - docker image build -t $CI_REGISTRY_IMAGE -t $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:5} . - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY - docker push $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:5} 11 . 8

Slide 46

Slide 46 text

Label A label is key=value pair to add more meta-information to the ressource 11 . 9

Slide 47

Slide 47 text

Label Standards http://label-schema.org/rc1/ 11 . 10

Slide 48

Slide 48 text

Labels in Dockerfile ARG BUILD_DATE ARG VCS_REF ARG USER ARG REPO_URL ARG NAME ARG LICENSE LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.docker.dockerfile="/Dockerfile" \ org.label-schema.license="$LICENSE" \ org.label-schema.name="$NAME" \ org.label-schema.vendor="$USER" \ org.label-schema.url="https://github.com/solidnerd/goinc/" \ org.label-schema.vcs-ref=$VCS_REF \ org.label-schema.vcs-url="$REPO_URL" \ org.label-schema.vcs-type="git" 11 . 11

Slide 49

Slide 49 text

Using Labels in gitlab-ci.yml build: image: docker before_script: - apk add --no-cache util-linux pciutils usbutils coreutils binutils findutils grep script: - docker build --build-arg LICENSE="MIT" --build-arg NAME=$CI_PROJECT_NAME --build-arg BUILD_DATE="$(date --rfc- 11 . 12

Slide 50

Slide 50 text

Using Digests A content-addressable identi er for Images docker run namespace/image@sha256:digest #Dockerfile FROM namespace/image@sha256:digest 11 . 13

Slide 51

Slide 51 text

User Switch All containers are running in the normal case as root user 11 . 14

Slide 52

Slide 52 text

Add User Switch to Dockerfile FROM alpine:3.8 ENV GO_USER=go \ GO_HOME=/app \ GO_UID=1000 \ GO_GID=1000 RUN addgroup -S $GO_USER -g ${GO_GID} \ && adduser -S \ -g $GO_USER \ -h $GO_HOME \ -u ${GO_UID} \ $GO_USER USER ${GO_USER} WORKDIR ${GO_HOME} COPY mybinary ${GO_HOME}/mybinary ENTRYPOINT ["${GO_HOME}/mybinary"] 11 . 15

Slide 53

Slide 53 text

Use Scratch FROM scratch COPY mybinary /mybinary ENTRYPOINT ["/mybinary"] 11 . 16

Slide 54

Slide 54 text

Use a Healthcheck FROM maven:3.5.0-jdk-8 as build RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ARG MAVEN_OPTS="-Dmaven.repo.local=.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jM COPY pom.xml /usr/src/app RUN mvn verify clean --fail-never # COPY now all sources COPY . /usr/src/app RUN mvn package FROM openjdk:8u131-jre-slim RUN apt-get update && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/ COPY --from=build /usr/src/app/target/hellowrold-0.0.1-SNAPSHOT.jar /app.jar HEALTHCHECK --interval=15s --timeout=15s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar", "/app.jar"] 11 . 17

Slide 55

Slide 55 text

Good Docker Images Own User (with User Switch) Contains only the application Labels to determine the content Healthcheck 12

Slide 56

Slide 56 text

Build Images without Docker 13 . 1

Slide 57

Slide 57 text

Another Approach with Kaniko Kaniko is an open source tool to build container images within containers can be Kubernetes or Docker without a daemon Builds every general Docker le The resulting Image after the build can be directly pushed to registry or exported as tarball It doesn't require any particular privilege for building the image Is able to remove timestamps to perfom repeatable builds 13 . 2

Slide 58

Slide 58 text

Kaniko with GitLab CI 13 . 3

Slide 59

Slide 59 text

Kaniko with GitLab CI (cont.) # .gitlab-ci.yml build:kaniko: stage: build image: name: gcr.io/kaniko-project/executor:debug-v0.6.0 entrypoint: ["/busybox/sh","-c"] before_script: - export KANIKO_DOCKERFILE="Dockerfile" - export KANIKO_DESTINATION="$CI_REGISTRY_IMAGE/$CI_JOB_NAME:$CI_COMMIT_REF_NAME" variables: KANIKO_DOCKERFILE: $CI_PROJECT_DIR/Dockerfile KANIKO_DESTINATION: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME script: - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\" - /kaniko/executor --context "$CI_PROJECT_DIR/$CI_JOB_NAME" --destination "$KANIKO_DESTINATION" 13 . 4

Slide 60

Slide 60 text

Open the doors for Q&A    [email protected] solidnerd solidnerd 14