Skip to content

Instantly share code, notes, and snippets.

@chooh
Last active October 20, 2020 09:56
Show Gist options
  • Save chooh/6b5522d28c51bc44b02c39d847866e21 to your computer and use it in GitHub Desktop.
Save chooh/6b5522d28c51bc44b02c39d847866e21 to your computer and use it in GitHub Desktop.
GitLab: How to build a docker image and run tests or generate documentation using the image

How to build a docker image and run tests or generate documentation using the image with GitLab

Let's say you have a ruby project. You write tests using rspec and you write documentation inside the code. And you are using awesome GitLab to host your git repo, run CI pipelines and store your docker images in registry.

Build an image.

First we need to build an image. But we want to leverage docker layer caching, because libraries (rubygems) doesn't update very often. That's why we do docker pull first, and docker build --cache-from after.

If you make a feature branch and update some libraries, you can't use layer with libraries form the master branch. That's why we try to docker pull for feature branch first, and docker pull for master branch after.

And we push built image after to the registry.

Run tests

We use our just built image by setting image for the job. We already have the code inside the image and we don't need to check it out again.

BUT there is a gotcha, current working directory is $CI_PROJECT_DIR and our source code lays in /app. Do cd /app in before_script.

Publish yard documentation with GitLab Pages

When GitLab runner starts a job with you image, it creates a project directory on the host, run a new docker container with the image and mounts project directory as a volume.

After pages is generated, GitLab waits for it in the project directory, that's why we need to move the docs from our docker container to the project directory.

#docker #gitlab-ci

image: docker:git
before_script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
variables:
CONTAINER_BRANCH_IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG
CONTAINER_MASTER_IMAGE: $CI_REGISTRY/$CI_PROJECT_PATH:master
stages:
- build
- test
build:
stage: build
script:
- >
if docker pull $CONTAINER_BRANCH_IMAGE; then
export CONTAINER_CACHE_IMAGE=$CONTAINER_BRANCH_IMAGE
else
docker pull $CONTAINER_MASTER_IMAGE || true
export CONTAINER_CACHE_IMAGE=$CONTAINER_MASTER_IMAGE
fi
- docker build --cache-from $CONTAINER_CACHE_IMAGE -t $CONTAINER_BRANCH_IMAGE .
- docker push $CONTAINER_BRANCH_IMAGE
.init-image: &base
image: "$CONTAINER_BRANCH_IMAGE"
variables:
GIT_STRATEGY: none
before_script:
- cd /app
- cp config/database.yml.sample config/database.yml
- cp config/redis.yml.sample config/redis.yml
rspec:
<<: *base
stage: test
script:
- bundle exec rspec
rubocop:
<<: *base
stage: test
script:
- bundle exec rake style
pages:
<<: *base
script:
- bundle exec yard
- rm -rf $CI_PROJECT_DIR/public && mkdir -p $CI_PROJECT_DIR/public
- cp -r doc/* $CI_PROJECT_DIR/public/
artifacts:
paths:
- public
only:
- master
FROM ruby:2.5.7
ENV LANG C.UTF-8
ENV RAILS_ROOT /app
WORKDIR /app
# Make an image layer with libraries, this will speed up consecutive builds
COPY Gemfile* ./
COPY vendor/ ./vendor/
RUN bundle install
COPY . .
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment