Skip to content

Instantly share code, notes, and snippets.

@CCFenner
Last active July 27, 2022 04:56
Show Gist options
  • Save CCFenner/89710c3a74b4744eae9ead94931f15a5 to your computer and use it in GitHub Desktop.
Save CCFenner/89710c3a74b4744eae9ead94931f15a5 to your computer and use it in GitHub Desktop.
How do validate Docker images on Docker Hub using Goss and Docker Compose

Docker Image Validation

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.

Goss

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 with Docker

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.yamlfile.

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

Goss with Docker Compose

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.

Docker Hub

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.

img

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.

Links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment