Do you publish container images to Docker Hub but have no idea how to test them upfront? Then read on and get to know how you can use goss
, docker-compose
and Docker Hub to automatically test your images before releasing them.
So Goss is a tool to validate server configurations. You define your assumption in a yaml
-style spec file and validate against them.
goss.yaml
user:
root:
exists: true
ccfenner:
exists: true
home: /Users/ccfenner
$ goss validate --format documentation
User: root: exists: matches expectation: [true]
User: ccfenner: exists:
Expected
: false
to equal
: true
User: ccfenner: home: skipped
Total Duration: 0.000s
Count: 3, Failed: 1, Skipped: 1
Read more about writing the tests in the official guide.
Goss also provides a wrapper for Docker, dgoss
. With this you can run a container, gather the test commands and extract them to a spec.
First use dgoss edit ..
to run your container, make sure you run with a shell that you can interact with.
$ dgoss edit -it --entrypoint bash node:lts
Inside the container you can now use goss
to record commands and their actual values.
$ goss autoadd user root
root:
exists: true
gid: 0
$ goss autoadd package git
git:
installed: true
versions:
- 1:2.11.0-3+deb9u5
When you now exit
the container, all recorded test cases are exported to a goss.yaml
file.
package:
git:
installed: true
versions:
- 1:2.11.0-3+deb9u5
user:
root:
exists: true
uid: 0
gid: 0
groups:
- root
home: /root
shell: /bin/bash
group:
root:
exists: true
gid: 0
When you now run dgoss run ..
, the container will be validated with the goss.yaml
file.
$ dgoss run -it --entrypoint bash node:lts
INFO: Starting docker container
INFO: Container ID: 7302d011
INFO: Sleeping for 0.2
INFO: Container health
INFO: Running Tests
Group: root: exists: matches expectation: [true]
Group: root: gid: matches expectation: [0]
User: root: exists: matches expectation: [true]
User: root: uid: matches expectation: [0]
User: root: gid: matches expectation: [0]
User: root: home: matches expectation: ["/root"]
User: root: groups: matches expectation: [["root"]]
User: root: shell: matches expectation: ["/bin/bash"]
Package: git: installed: matches expectation: [true]
Package: git: version: matches expectation: [["1:2.11.0-3+deb9u5"]]
Total Duration: 0.008s
Count: 10, Failed: 0, Skipped: 0
INFO: Deleting container
So lets bring docker-compose
into the game to speed up the build and test process.
Docker Compose is a tool to orchestrace Docker container. You define the containers and how they interact in a docker-compose.yml
file (see Compose file reference for details).
In this case we will use it to handle the build and test execution. Let's assume you have this simple Dockerfile
in the project root.
FROM node:lts
RUN npm config --global set @sap:registry https://npm.sap.com/
First create a docker-compose.yml
in the project root defining your image as a servcice
and starting goss
.
version: '3'
services:
app:
build: .
command: goss validate --format documentation
Now you can already build and startup your image using docker-compose
.
$ docker-compose up
...
app_1 | Error: Cannot find module '/goss'
Don’t panic, this should fail as the goss
execuable is not yet available in the container.
To achieve this you will use Docker compose to share the executable from Goss’ Docker image with your app container.
version: '3'
services:
app:
build: .
command: goss validate --format documentation
depends_on:
- goss
environment:
PATH: $PATH:/goss
volumes:
- goss-executable:/goss
goss:
image: aelsabbahy/goss
command: goss --version
volumes:
- goss-executable:/goss
volumes:
goss-executable:
$ docker-compose up
...
app_1 | File error: open ./goss.yaml: no such file or directory
Now as the goss
executable is available in the container, you need to add your spec file.
version: '3'
services:
app:
...
environment:
GOSS_FILE: /goss-file/goss.yaml
...
volumes:
- .:/goss-file
...
goss:
...
$ docker-compose up
...
app_1 | User: root: exists: matches expectation: [true]
app_1 | Command: npm config get registry: exit-status: matches expectation: [0]
app_1 | Command: npm config get registry: stdout: matches expectation: [https://registry.npmjs.org/]
app_1 |
app_1 | Total Duration: 0.319s
app_1 | Count: 3, Failed: 0, Skipped: 0
That’s it, now you can easily define your assumptions regarding your container in your goss.yaml
file and validate the current Dockerfile
using docker-compose up
.
On Docker Hub container images can be build and published. One feature of the Docker Hub’s build is autotest, that fits well to the testing approach described above.
After you setup your repository and automated build, you can setup autotest in the build settings.
Docker Hub expects a docker-compose.test.yml
file in the project root that creats a service named sut
(system under test) for autotest to work (description). So you need to rename the docker-compose.yml
file and the app
service.
When this is done, Docker Hub will do the build and execute sut
service and only if this exits with 0
the built image is published.