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/
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
$ 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:  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:  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.
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 firstname.lastname@example.org