Semantic Docker with Semantic Release, Docker, and Travis CI
This tutorial will show you how to combine semantic-release + Docker + CI to automatically version your docker images based on your commit messages!
Why
When you develop software and release it via Docker, it is nice to know which images include breaking changes, minor changes, or bug fixes. And some changes don’t require a new image– for example, if you are just doing developer chores (updating developer dependencies, documentation, or comments, etc). Semantic Versioning (“SemVer”) clearly communicates what kind of changes each new build contains.
But manually keeping track of this information is a slog. Instead, you can follow the Conventional Commits standard and use a tool called semantic-release to do the hard work for you.
I’ll provide instructions for a pipeline which will automatically update your semantic version and rebuild a new docker image with that version.
Prerequisites
- an app with a Dockerfile which works
- an account with travis-ci — you could use another CI provider, but you’ll have to alter these steps appropriately for that CI system.
Step 1: Make sure your Dockerfile works
docker build . -t YOUR_REPO/YOUR_PROJECT:v1.0.0
You must resolve any errors here before proceeding.
If you do not have a Dockerfile yet, you must set one up that works with your app. The contents of your Dockerfile will depend on how your app is set up, which language(s) it uses, etc. Either search for “Dockerfile example” + the name of your application framework, or follow the official getting started guide.
Step 2: Make sure you can log in to the docker registry and push
docker login # follow prompts docker push YOUR_REPO/YOUR_PROJECT:v1.0.0 YOUR_REPO/YOUR_PROJECT:v1.0.0
Step 3: Initialize a package.json file if you don’t have one
npm init # and follow prompts
Step 4: Install @semantic-release/commit-analyzer, @semantic-release/git, semantic-release, semantic-release-docker as development dependencies:
npm install --save-dev @semantic-release/commit-analyzer npm install --save-dev @semantic-release/git npm install --save-dev semantic-release npm install --save-dev semantic-release-docker
Step 5: Check package.json and configure your semantic-release pipeline
You should have something like:
{ "name": "YOUR_PROJECT_NAME", "version": "1.0.0", "description": "", "scripts": { "semantic-release": "semantic-release" }, "devDependencies": { "@semantic-release/commit-analyzer": "^6.1.0", "@semantic-release/git": "^7.0.8", "semantic-release": "^15.13.3", "semantic-release-docker": "2.1.0" } }
(package versions may vary)
You want to tell semantic-release which plugins to use and what order to put them in. You do this by adding a release
key to your package.json:
{ "name": "YOUR_PROJECT_NAME", "version": "1.0.0", "description": "", "scripts": { "semantic-release": "semantic-release" }, "devDependencies": { "@semantic-release/commit-analyzer": "^6.1.0", "@semantic-release/git": "^7.0.8", "semantic-release": "^15.13.3", "semantic-release-docker": "2.1.0" }, "release": { "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/git", "semantic-release-docker" ], "publish": [ { "path": "semantic-release-docker", "name": "YOUR_REPO_NAME/YOUR_PROJECT_NAME" } ] } }
Step 6: Dry-run semantic release to make sure that worked
DOCKER_USERNAME=yourusername DOCKER_PASSWORD=yourpassword npx semantic-release --dry-run
NOTE: putting your DOCKER_USERNAME and DOCKER_PASSWORD on the command line like this isn’t great for security, but it is a fast way to test. Our real setup will use encrypt variables in TravisCI. You may want to edit your shell history after running this test or use history -c
to clear it.
What you should see is a log of different semantic-release steps, with no errors. semantic-release will report that it is not releasing since this is a dry run.
Step 7: Build your bin/deploy script
bin/deploy is the name we use for all our deploy scripts, but you could use scripts/deploy or any name really. You’ll just need to alter the .travis.yml file below as appropriate.
#!/bin/sh set -e # These steps may vary depending on your project-- in my case, this builds all my assets so that they are available to docker npm install -g npm (cd assets; npm install; npm run deploy) npm install # Docker build and semantic release to docker registry docker build . -t YOUR_REPO_NAME/YOUR_PROJECT_NAME npx semantic-release
Every step you need to build the application from scratch goes here and put npx semantic-release at the end. You’ll need this deploy script to be marked executable.
chmod u+x bin/deploy
Step 8: Add your repo to Travis
Use the repositories menu in TravisCI to set up your application for CI, if you have not already.
Step 9: Build your .travis.yml
We don’t want to have to deploy from our laptops every time. Instead, we’d prefer a deploy to happen automatically every time we update our code in GitHub. We use Travis to do that. We need to tell Travis what our build steps are.
language: elixir
elixir:
- 1.8.0
otp_release:
- 21.2.2
env:
matrix:
- MIX_ENV=test
global:
- secure: # use `travis encrypt DOCKER_USERNAME=yourusername --add` and travis encrypt DOCKER_PASSWORD=yourpassword --add` to set up the username and password for your docker registry account services:
- docker
before_script:
- nvm install v10.15.0
- mix do ecto.create, ecto.migrate
script:
- mix test
deploy:
provider: script
script: bin/deploy
skip_cleanup: true
on:
branch: master
This will look different for different languages. Starting from a working .travis.yml for your language, you’ll make some additions. You’ll add:
services:
- docker
This ensures that Docker is up and running for you before your tests and deployment run.
You’ll add a deploy section:
deploy:
provider: script
script: bin/deploy
skip_cleanup: true
on: branch: master
This runs your deploy script any time a passing build lands in the master branch.
You also need to set environment variables in Travis for semantic-release-docker:
travis encrypt DOCKER_USERNAME=yourusername --add
travis encrypt DOCKER_PASSWORD=yourpassword --add
Step 10: Push all your changes (package.json, bin/deploy, .travis.yml) to GitHub
Commit your changes using a conventional commit message.
Push your changes to GitHub, to the branch that you configured in the deploy section above. At this point, Travis should see your changes and start a build.
Step 11: Watch your build
You should be able to see the build in the TravisCI UI. Watch the build logs. After some time, the build should turn green, meaning your build succeeded.
If the build fails, you’ll need to study the error and do some searching. Double check that all of the above configuration is properly in place.
Step 12: Check the Docker registry
Once you have a green build on the deploy branch, you should have a new docker image in the Docker registry. Visit your Docker registry and check that the build is there. If you don’t see it after a successful build, double check the build log and ensure that the semantic-release actually logged a docker push.
Revel in Victory!
Originally published at revelry.co on March 15, 2019.