Tear down docker containers after merge and stop environments

I am after the ability to control my docker environments via my CI Pipelines instead of having a cron or docker container doing a clean up operation on the target VM/Machine.

What the below is trying to achieve is this:

  • On creation of a PR: Create a demo area for my PR container
  • On update of a PR: Update the demo area container
  • On merge to master: Update the review area container & destroy the PR container/env
  • On tagging of master: Update the production container
    # Helpers:
    # Gitlab Variable: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
    before_script:
     - export REVIEW_FRONTEND_URL=review.example.co.uk
     - export BRANCH_REVIEW_FRONTEND_URL="${CI_COMMIT_REF_NAME}.review.example.co.uk"
     - export DEVELOPMENT_IMAGE_TAG=$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
     - env

    stages:
      - build_image
      - deploy_image

    ## PR Demo branch start
    build_pr_demo_branch:
      stage: build_image
      image: docker:19.03
      services:
        - docker:dind
      script:
        - docker login -u gitlab-ci-token -p "${CI_BUILD_TOKEN:-$CI_JOB_TOKEN}" $CI_REGISTRY
        - docker build -t $DEVELOPMENT_IMAGE_TAG .
        - docker push $DEVELOPMENT_IMAGE_TAG
      only:
        - branches
      except:
        - master

    deploy_pr_demo_branch:
      image: docker:19.03
      stage: deploy_image
      script:
        - docker login -u gitlab-ci-token -p "${CI_BUILD_TOKEN:-$CI_JOB_TOKEN}" $CI_REGISTRY
        - docker pull $DEVELOPMENT_IMAGE_TAG
        - docker ps -aq --filter name=${CI_COMMIT_REF_NAME}-review-example | xargs docker stop | xargs docker rm
        - docker run -d -l "traefik.enable=true" -l "traefik.port=3000" -l "traefik.frontend.rule=${BRANCH_REVIEW_FRONTEND_URL}" --name ${CI_COMMIT_REF_NAME}-review-example ${DEVELOPMENT_IMAGE_TAG}
      environment:
        name: review/$CI_COMMIT_REF_NAME
        url: http://$CI_COMMIT_REF_NAME.review.example.co.uk
      only:
        - branches
      except:
        - master
    ## PR Demo branch end
    ## ---------------------------
    ## Review start
    build_review:
      stage: build_image
      image: docker:19.03
      services:
        - docker:dind
      script:
        - docker login -u gitlab-ci-token -p "${CI_BUILD_TOKEN:-$CI_JOB_TOKEN}" $CI_REGISTRY
        - docker build -t $DEVELOPMENT_IMAGE_TAG .
        - docker push $DEVELOPMENT_IMAGE_TAG
      only:
        - master

    deploy_review:
      image: docker:19.03
      stage: deploy_image
      script:
        - apk add jq curl
        - |
          source_branch=$(curl --request GET --url "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_BEFORE_SHA/merge_requests" --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" | jq -r .[0].source_branch)
        - |
          branch_name=$(echo $source_branch | sed 's/ /-/g')
        - |
          echo $branch_name
        - docker pull $DEVELOPMENT_IMAGE_TAG
        # Stop PR Demo branch
        - docker ps -qa --filter name=${branch_name}-review-example | xargs docker stop | xargs docker rm
        # Kill container to allow new version to be used
        - docker ps -aq --filter name=${CI_COMMIT_REF_NAME}-review-example | xargs docker stop | xargs docker rm
        - docker run -d -l "traefik.enable=true" -l "traefik.port=3000" -l "traefik.frontend.rule=${REVIEW_FRONTEND_URL}" --name review-example ${DEVELOPMENT_IMAGE_TAG}
      environment:
        name: review
        url: http://$CI_COMMIT_REF_NAME.$REVIEW_FRONTEND_URL
      only:
        - master
    ## Review end
    ## ---------------------------
    ## Delivery start
    build_delivery:
      stage: build_image
      image: docker:19.03
      services:
        - docker:dind
      script:
        - docker login -u gitlab-ci-token -p "${CI_BUILD_TOKEN:-$CI_JOB_TOKEN}" $CI_REGISTRY
        - docker build -t $DEVELOPMENT_IMAGE_TAG .
        - docker push $DEVELOPMENT_IMAGE_TAG
      only:
        - tag

    deploy_delivery:
      image: docker:19.03
      stage: deploy_image
      script:
        - apk add jq curl
        - |
          source_branch=$(curl --request GET --url "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_BEFORE_SHA/merge_requests" --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" | jq -r .[0].source_branch)
        - |
          branch_name=$(echo $source_branch | sed 's/ /-/g')
        - |
          echo $branch_name
        - docker login -u gitlab-ci-token -p "${CI_BUILD_TOKEN:-$CI_JOB_TOKEN}" $CI_REGISTRY
        - docker pull $DEVELOPMENT_IMAGE_TAG
        # Kill container to allow new version to be used
        - docker ps -aq --filter name=example | xargs docker stop | xargs docker rm
        - docker run -d -l "traefik.enable=true" -l "traefik.port=3000" -l "traefik.frontend.rule=${REVIEW_FRONTEND_URL}" --name example ${DEVELOPMENT_IMAGE_TAG}
      environment:
        name: review
        url: http://$CI_COMMIT_REF_NAME.$REVIEW_FRONTEND_URL
      only:
        - tag
    ## Delivery end

Above is my current .gitlab-ci.yml. The first section is working fine and creates the demo and updates. The second section doesn’t destroy the demo container as if I rebase from master the branch name is not correct.

Is there a simple/easier/better way on doing this as I feel like I am missing something here but can’t see the wood through the trees :disappointed:

1 Like