Ever tested your App but then have it fail once you've put it in a Docker image? Not anymore!

Its important that when your are using Docker for deployment, you are no longer shipping code, you are shipping images! That means instead of testing your code to prove you app is working, you should test your Docker image works!

OK I get it, But how?

Introducing GOSS, the simple and lightweight server testing tool. We can use GOSS to test that:

  • Packages are installed
  • Configuration is correct
  • Services/Processes are running
  • Users exist
  • File permissions are correct
  • Ports are open
  • Even more. For a full list check https://github.com/aelsabbahy/goss/

Installing GOSS

You can use the code below to download GOSS or follow instructions on the GitHub page: https://github.com/aelsabbahy/goss

# Download GOSS. v0.3.9 is the latest at time of writing
sudo curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.9/goss-linux-amd64 -o /usr/local/bin/goss

# Set permissions on GOSS executable
sudo chmod +rx /usr/local/bin/goss

# Download DGOSS, a wrapper for Docker and GOSS
sudo curl -L https://raw.githubusercontent.com/aelsabbahy/goss/v0.3.9/extras/dgoss/dgoss -o /usr/local/bin/dgoss

# Set permissions on DGOSS executable
sudo  chmod +rx /usr/local/bin/dgoss

Writing our first GOSS test

Now GOSS is installed we can start adding tests, in the example below I add tests for making sure /opt/app is a folder and making sure the NodeJS executable is available. I'm going to be testing a pre-built image called myapp.

$ dgoss edit --entrypoint="" myapp sleep 1000
/goss # goss add file /usr/local/bin/node
Adding File to './goss.yaml':
...

/goss # goss add file /opt/app
Adding File to './goss.yaml':
...

/goss # exit
INFO: Copied '/goss/goss.yaml' from container to '.'

We can then see the tests in the newly created goss.yml file which has been created for us:

$ cat goss.yaml 
file:
  /opt/app:
    exists: true
    mode: "0755"
    size: 4096
    owner: root
    group: root
    filetype: directory
    contains: []
  /usr/local/bin/node:
    exists: true
    mode: "0751"
    size: 46252712
    owner: root
    group: root
    filetype: file
    contains: []

This is just scratching the surface of what GOSS can do, for a full list of what we can test for see the GitHub page: https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#available-tests

Let's run our new tests

$ dgoss run --entrypoint="" myapp sleep 100
INFO: Starting docker container
INFO: Container ID: ba7bcb91
INFO: Sleeping for 0.2
INFO: Container health
INFO: Running Tests
File: /opt/app: exists: matches expectation: [true]
File: /opt/app: mode: matches expectation: ["0755"]
File: /opt/app: owner: matches expectation: ["root"]
File: /opt/app: group: matches expectation: ["root"]
File: /opt/app: filetype: matches expectation: ["directory"]
File: /opt/app: size: matches expectation: [4096]
File: /usr/local/bin/node: exists: matches expectation: [true]
File: /usr/local/bin/node: mode: matches expectation: ["0755"]
File: /usr/local/bin/node: owner: matches expectation: ["root"]
File: /usr/local/bin/node: group: matches expectation: ["root"]
File: /usr/local/bin/node: filetype: matches expectation: ["file"]
File: /usr/local/bin/node: size: matches expectation: [46252712]


Total Duration: 0.003s
Count: 12, Failed: 0, Skipped: 0
INFO: Deleting container
willem@boogaloo:~/Respositories/phonito-backend$ 

Looking good! No failed test, as expected. Now we can make changes to our Dockerfile without having to worry about breaking our App as long as we have proper tests in place.

What about our App?

We could run application tests inside our Docker image using the command test in GOSS, that could look something like this:

$ cat goss.yaml
command:
  version:
    exit-status: 0
    exec: "npm test" # Run test in NodeJS app
    stderr: []
    timeout: 10000 # in milliseconds
    skip: false

This allows us to check that we have copied our application into our Docker image correctly and that all our dependencies are present and correct. The possibilities are endless when it comes to what we can test.

Final Thoughts

A lot of developers fall into the trap of using exact versions of software, such as installing an exact version of a dependency like NodeJS or Java, or using a fixed version of linux for their FROM instead of latest. Whilst this is an easy way to have a stable Docker image, it can lead to never receiving security patches and having to spend a lot of time fixing things when they eventually do upgrade software. Testing our Docker image allows us to use up to date software without the worry of having an unstable application.

Any feedback? Hit me up on our Slack! Or email me at will@phonito.io