Automate Docker deployment with Gitlab

Automate Docker deployment with Gitlab
Going to deploy single Docker container to remote server.
Good for all sorts of small projects and pages, like this blog :)

.gitlab-ci.yml

Create .gitlab-ci.yml file in project root

# Setup 2 steps:
#   dockerize Build container
#   deploy    Deploy to remote server
stages:
  - dockerize
  - deploy
  
dockerize:
  stage: dockerize
  image: docker
  # Run this step only when code is pushed into master branch.
  # Might want to make it "tags" to dockerize only releases
  only:
    - master
  # Use Docker in Docker service, to build Docker in Docker
  services:
    - docker:dind
  script:
    # Login to Gitlab Docker registry using built-in variables
    - docker login
      -u "$CI_REGISTRY_USER"
      -p "$CI_REGISTRY_PASSWORD"
      $CI_REGISTRY
	# About Nginx static files Dockerfile setup: 
	# https://mcsneaky.com/static-files-in-dockerized-nginx/
    # Build it! Name will be project_name:branch_name
    - docker build --pull -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
    # Push freshly built image to Gitlab registry
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG

deploy:
  stage: deploy
  # Use this as base image to get small SSH container
  image: instrumentisto/rsync-ssh
  only:
    - master
  script:
    # Add key, it needs to be set up as pipeline variable
    - eval $(ssh-agent -s)
    - echo "$DEPLOYER_KEY" | tr -d '\r' | ssh-add - > /dev/null
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    # Remove known hosts check
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
    # Explained down below
    - ssh -t [email protected] "docker login -u "$CI_DEPLOY_USER" -p "$CI_DEPLOY_PASSWORD" $CI_REGISTRY &&
      docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG &&
      docker stop example-name; docker rm example-name;
      docker run -d -p 31227:80 --name example-name $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
.gitlab-ci.yml

Deploy script explained line by line

# SSH into server, run last argument as command and disconnect
ssh -t [email protected] ""
# From remote server login into Gitlab registry
# how to get and setup deploy tokens
"docker login -u "$CI_DEPLOY_USER" -p "$CI_DEPLOY_PASSWORD" $CI_REGISTRY"
# Pull new Docker image
docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG &&
# Stop and remove existing container, use ";" instead of &&
# since server does not have this container when deploying first time
docker stop example-name; docker rm example-name;
# Start container in background, expose port 80 to 31227 and name it
docker run -d -p 31227:80 --name example-name $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"

Basic Nginx server block for web services


Really basic server block is needed to proxy traffic to Docker container

Location of it is based on your host operating system. For most Debian based OSes it is /etc/nginx/sites_available/example.com.conf and linked to /etc/nginx/sites_enabled/example.com.conf

For OpenSUSE it is /etc/nginx/vhosts.d/example.com.conf

server {
    server_name example.com;

    location ~ / {
        # Add headers, so application knows it is behind proxy
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        # Proxy to container. Port must be same as in deploy script
        proxy_pass http://127.0.0.1:31227;
    }
}
example.com.conf

It does not do any GZIP / caching / certing etc. But it is really easy to enable, based on server block on host machine.

Will write another short post about it in future