In this guide, we will explore in detail what Goss is, how it is used to validate and maintain the health of services, and how you can easily integrate it into your Docker images. For those looking to improve the quality of their development and deployments, Goss presents itself as a reliable and efficient solution.
What is Goss?
Goss is an infrastructure service validation tool that can be used to verify that a Docker service is working correctly. You can use Goss to create and run integration tests on your Docker service, allowing you to ensure that it is configured correctly and is responding as expected. Goss is easy to use and integrates well with Docker, making it an excellent choice for validating Docker services.
Uses of the Goss tool
Goss can be used in Linux to validate a variety of aspects of service configuration and behaviour. Some examples of uses of Goss in Linux include:
- Validation of network configurations: Goss can be used to verify that network services, such as DNS and DHCP, are configured correctly and responding to requests.
- Validation of security settings: Goss can be used to verify that security settings, such as firewall and SSH access, are configured correctly.
- Validation of system configurations: Goss can be used to verify that system services, such as memory and disk space settings, are configured correctly.
- Validation of application services: Goss can be used to verify that application services, such as a web server or database, are functioning correctly and responding to requests.
- Validation of monitoring configurations: Goss can be used to verify that monitoring services, such as Zabbix or Nagios, are configured correctly and collecting the correct data.
It is important to note that these are just some of the possible uses of Goss in Linux, as its flexibility allows it to adapt to a wide variety of environments and situations.
Installation and service validation: How to validate with Goss
Let’s see an example of how to validate with Goss, following the general steps below:
- Install Goss: To make use of Goss, you will first need to install it on your Linux system. You can do this by downloading the binary package from the Goss download page or by using a package manager such as apt or yum.
- Create the tests: Goss uses a YAML scripting language to specify the tests to be performed. Create a YAML file with the tests you want to run on your service.
- Run the tests: use the goss run command to run the tests specified in the YAML file.
- Review results: Goss presents test results in a standardized format. If any test fails, the error will be reported, and the problem detailed.
Example:
# Install Goss curl -fsSL https://goss.rocks/install | sh # Create a test file to verify that the web service is working correctly. echo "http: # Verify that the server is responding status: 200 # Verify that the server is responding with the expected content body: /Welcome to my website/" > test.yaml # Execute the tests goss --gossfile test.yaml validate
In this example, the web service is verified to be working correctly by responding with a status code 200 and a specific content. If the test fails, the error will be reported.
How to configure Goss in a docker image
It is possible to use Goss to validate services inside a Docker container by adding the necessary instructions to run it in the Dockerfile. By doing so, it will automatically run every time the container is built or started.
Changes to our compose
The first thing we are going to do is to change the way our docker-compose reads the docker image.
This is the normal way to add images to a service in docker, where they are downloaded from the official docker repositories.
version: "3" services: odoo14: image: odoo:14.0 ... nginx: image: nginx ... postgres-odoo: image: postgres:12.8 ...
We will change it to create our own image and for this we are going to create a Dockerfile for each service where we are going to have goss.
vagrant@master:~/odoo$ cat dockerfile/odoo14/Dockerfile FROM odoo:14.0 vagrant@master:~/odoo$ cat dockerfile/postgres-odoo/Dockerfile FROM postgres:12.8 vagrant@master:~/odoo$ cat dockerfile/nginx/Dockerfile FROM nginx With these changes we build the image using the previously created Dockerfile, with this we get to add more parameters or improvements. We raise the docker-compose and we already have the containers. vagrant@master:~/odoo$ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------------------------------------------------------- nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0.0:443->443/tcp,:::443->443/tcp, 0.0.0.0.0:80->80/tcp,:::80->80/tcp odoo14 /entrypoint.sh odoo Up 0.0.0.0.0:8069->8069/tcp,:::8069->8069/tcp, 8071/tcp, 8072/tcp portainer-odoo /portainer Up 9000/tcp postgres-odoo docker-entrypoint.sh postgres Up 0.0.0.0.0:5432->5432/tcp,:::5432->5432/tcp
In the status column we see that it is Up but we do not know if it’s Healthy or not, for this we are going to configure goss.
We add goss
To validate services, specific test files must be created for each service to be validated. These files should specify the expected parameters and behaviors of the service, and Goss will compare these parameters with the actual values of the service to determine if the service is functioning correctly.
How are we going to configure it?
- Nginx will check if it has its own port open and also that all services are active, otherwise it will not start the service.
- Odoo checks if it has its own port active and if it answers the call to the web, then it will check that it has connection to postgres and that it can access the database.
- Postgres will check only if it has its own port open.
The checks to itself we can put them on the file, goss.yaml. While the checks to other services will be added to the file goss-command.yaml (This name is indicative and can be changed).
Odoo Goss Files
This file verifies that it is listening on port 8069 and will make a call to itself that has to respond with a status code 200 for proper operation.
$ cat dockerfile/odoo/goss/goss.yaml port: tcp:8069: listening: true http: http://localhost:8069/web/database/selector: status: 200 allow-insecure: false no-follow-redirects: false timeout: 5000 body: []
For the goss-command.yaml file, we are going to perform tests to check the operation of postgres. First, if it responds to the service and then if it can log into the database, for this option we have to have the client of the manager installed on the machine.
$ cat dockerfile/odoo/goss/goss-command.yaml addr: tcp://postgres-odoo:5432: reachable: true timeout: 500 command: PGPASSWORD=$${MY_PASSWORD} psql -h postgres-odoo -U ${MY_USER} -d postgres: title: Ensure we have valid credentials exit-status: 0 timeout: 50000 # 5s
Postgres goss files
Postgres will only check if port 5432 is open.
$ cat dockerfile/postgres/goss/goss.yaml port: tcp:5432: listening: true
nginx goss files
The first check that nginx will do is to verify if you have port 443 open.
$ cat dockerfile/nginx/goss/goss.yaml port: tcp:443: listening: true
We will use nginx as the main service to check all the other services, it will be the last one to fully wake up as it has to wait until the other services have done their checks.
We will add the checks to the services and if any service does not work we can verify its operation in another way, for example, the portainer service we have made a call to the web and if it returns a code 200 it means that it has been able to get up correctly.
$ cat dockerfile/nginx/goss/goss-command.yaml addr: tcp://postgres-odoo:5432: reachable: true timeout: 500 tcp://odoo14:8069: reachable: true timeout: 500 http: http://portainer-odoo:9000: status: 200 allow-insecure: false no-follow-redirects: false timeout: 5000 body: []
Add goss to the dockerfile
To use Goss from a Dockerfile, you must first add the instruction to install on the system. This can be done using the install command provided by the project or by using a previously built container image with Goss already installed.
Once Goss is installed, instructions can be added to copy the Goss test files to the container and run Goss. For example, you can add a COPY statement to copy the test files from the host file system to the container, and then a CMD or ENTRYPOINT statement to execute and run the tests.
Let’s configure the Dockerfiles of our infrastructure.
Odoo Dockerfile
FROM odoo:14.0 USER root RUN apt-get update RUN apt-get install curl -y ENV GOSS_VERSION v0.3.11 RUN curl -L https://github.com/aelsabbahy/goss/releases/download/$GOSS_VERSION/goss-linux-amd64 -o /usr/local/bin/goss && \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ chmod +rx /usr/local/bin/goss &&&. goss --version COPY goss/ /goss USER odoo CMD goss -g /goss/goss/goss-command.yaml validate -r 5m && exec odoo HEALTHCHECK --interval=1s --timeout=6s CMD goss -g /goss/goss.yaml validate
This example uses an Odoo 14 base image, install it, copy the directory, which will have the two previously created files, to the container and run it to validate the web service.
We perform two checks first we run the goss-command.yaml file and after its verification Odoo starts. Then, it performs a Healthcheck every second with the verification of the goss.yaml file.
Dockerfile of postgres
FROM postgres:12.8 USER root RUN apt update RUN apt install curl -y ENV GOSS_VERSION v0.3.11 RUN curl -L https://github.com/aelsabbahy/goss/releases/download/$GOSS_VERSION/goss-linux-amd64 -o /usr/local/bin/goss && \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ chmod +rx /usr/local/bin/goss &&&. goss --version COPY goss/ /goss HEALTHCHECK --interval=1s --timeout=6s CMD goss -g /goss/goss.yaml validate
Similar example, but with the postgres base image but with its respective checks.
It is important to mention that when running the tests from within a container, the tests will be validating the configuration and behavior of the service within the context of the container, rather than on the host.
Status of services
A Docker container can have three different health states: “healthy”, “unhealthy” or “health: starting”.
- “Healthy” means that the container is running correctly and meeting all specified health conditions.
- “Unhealthy” means that the container is not meeting one of the specified health conditions. This may be due to a problem with the service running inside the container or a problem with the container itself.
- “Health: starting” means that the container is starting and its health status has not yet been determined. This may be because the service has not yet finished starting or because the health tests have not yet been run.
We install the services
Once the instructions have been added, the command “docker-compose up -d” can be used to start the containers and run the Goss tests automatically.
You can use the “docker-compose ps” command to see the status of the containers in your compose file. If a container is “healthy”, it will be shown next to “Up”. If a container is failing it will be shown as “unhealthy”.
$ docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------------------------------------------------------- metabase /app/run_metabase.sh /bin/ ... Up (healthy) 3000/tcp netdata time bash starter.sh Up (healthy) 0.0.0.0.0:19999->19999/tcp,:::19999->19999/tcp nginx-odoo /docker-entrypoint.sh /bin ... Up (healthy) 0.0.0.0.0:443->443/tcp,:::443->443/tcp, 0.0.0.0.0:80->80/tcp,:::80->80/tcp odoo14 /entrypoint.sh /bin/bash - ... Up (healthy) 0.0.0.0.0:8069->8069/tcp,:::8069->8069/tcp, 8071/tcp, 8072/tcp portainer-odoo /portainer --admin-passwor ... Up 9000/tcp postgres-odoo docker-entrypoint.sh postgres Up (healthy) 0.0.0.0:5432->5432/tcp,:::5432->5432/tcp
What happens if a service goes down?
We are going to stop the database service by simulating that the database is down or could not be installed for some reason.
To stop a specific service in a compose file, you can use the command “docker-compose stop [service name]“.
$ docker-compose stop postgres-odoo Stopping postgres-odoo ... done
Once you have stopped the service, you can check the status again with docker-compose ps, where we can see that the services we have checking postgres are unhealthy or trying to start.
devops@chakray:~/gitlab-chakray/chdo/chdo/chdo-odoo-platform/odoo14-compose$ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------------------------------------------ metabase /app/run_metabase.sh /bin/ ... Up (healthy) 3000/tcp netdata time bash starter.sh Up (health: starting) 0.0.0.0.0:19999->19999/tcp,:::19999->19999/tcp nginx-odoo /docker-entrypoint.sh /bin ... Up (unhealthy) 0.0.0.0.0:443->443/tcp,::::443->443/tcp, 0.0.0.0.0:80->80/tcp,::::80->80/tcp odoo14 /entrypoint.sh /bin/bash - ... Up (health: starting) 0.0.0.0.0:8069->8069/tcp,:::8069->8069/tcp, 8071/tcp, 8072/tcp portainer-odoo /portainer --admin-passwor ... Up 9000/tcp postgres-odoo docker-entrypoint.sh postgres Exit 0
If you want to check the health status of the containers in real time, you can use the command “docker-compose logs -f” to view the logs of the containers while they are running.
nginx-odoo | Attempt #177: nginx-odoo | ...F nginx-odoo | nginx-odoo | Failures/Skipped: nginx-odoo | nginx-odoo | Addr: tcp://postgres-odoo:5432: reachable: nginx-odoo | Expected nginx-odoo | <bool>: false nginx-odoo | to equal nginx-odoo | <bool>: true nginx-odoo | nginx-odoo | Total Duration: 0.010s nginx-odoo | Count: 4, Failed: 1, Skipped: 0 nginx-odoo | Retrying in 1s (elapsed/timeout time: 177.516s/5m0s)
“Count” is the total number of tests executed. “Failed” is the number of tests that failed and “Skipped” is the number of tests that were skipped in the execution.
For example, if the result of running is “Count: 4, Failed: 1, Skipped: 0”, it means that 4 tests were run in total, one of them failed and none was skipped.
In case there are any failed tests, it will show you details about which tests failed and why. You can use this information to correct the problems and re-run the failed tests.
Service is up and running again
Once you have fixed the problems that caused the service to go down and we start it again and recheck if the container is in a healthy state.
devops@chakray:~/gitlab-chakray/chdo/chdo/chdo-odoo-platform/odoo14-compose$ docker-compose up -d netdata is up-to-date portainer-odoo is up-to-date Starting postgres-odoo ... done metabase is up-to-date odoo14 is up-to-date nginx-odoo is up-to-date
We see that it has already connected and we have made sure that the result is “Count: [x], Failed: 0, Skipped: 0″, indicating that all tests have passed successfully and there are no errors.
nginx-odoo | Attempt #272: nginx-odoo | ...F nginx-odoo | nginx-odoo | Failures/Skipped: nginx-odoo | nginx-odoo | Addr: tcp://postgres-odoo:5432: reachable: nginx-odoo | Expected nginx-odoo | <bool>: false nginx-odoo | to equal nginx-odoo | <bool>: true nginx-odoo | nginx-odoo | Total Duration: 0.005s nginx-odoo | Count: 4, Failed: 1, Skipped: 0 nginx-odoo | Retrying in 1s (elapsed/timeout time: 273.438s/5m0s) nginx-odoo | nginx-odoo | nginx-odoo | Attempt #273: nginx-odoo | .... nginx-odoo | nginx-odoo | Total Duration: 0.004s nginx-odoo | Count: 4, Failed: 0, Skipped: 0
If you still have problems with the container, you can check the container logs again with the command “docker-compose logs [service name]” to get more information about the problem.
Mapping goss
Why map a file?
Mapping a goss.yaml file to a Docker container has several advantages:
- Improved flexibility: By mapping a goss.yaml file into a container, you can customize the configuration to suit your specific needs, rather than being limited by the default Dockerfile configuration.
- Enables configuration reuse: By mapping a goss.yaml file to a container, you can reuse the same configuration in several different containers or environments, instead of having to create a different configuration for each container or environment.
- Makes it easy to update the configuration: By having the configuration outside the container, you can easily update it without having to rebuild the container image.
In summary, mapping a goss.yaml file into a Docker container allows you to have greater control over configuration, improve flexibility, and facilitate development and upgrades.
Mapping a Goss configuration file
You can map a configuration file into a Docker container at image build time or at container run time.
To do this we create a file with the same name in a directory. In this file we add the checks we need.
$ cat configs/odoo14/goss-command.yaml addr: tcp://postgres-odoo:5432: reachable: true timeout: 500 command: PGPASSWORD=$${MY_PASSWORD} psql -h postgres-odoo -U ${MY_USER} -d postgres: title: Ensure we have valid credentials exit-status: 0 timeout: 50000 # 5s
Mapping a goss.yaml file into a Docker container will overwrite any settings specified in the original Dockerfile in the image. This is because the mapped goss.yaml file is linked to the container at runtime, and takes precedence over any settings specified in the Dockerfile.
It is important to note that this only applies to the configuration. If there are any changes to the container that do not relate to Goss, such as a software dependency, file system changes, etc, these will not be affected by the mapped goss file.
Configuration of docker-compose.yml
To map a goss.yaml file into a Docker container when using Docker Compose, you must specify the path to the goss.yaml file on your local file system in the compose file and the path within the container where you want to place the goss.yaml file.
For example, if your goss.yaml file is located in the path “./configs/odoo14/goss-command.yaml” and you want to map it to the container in the path “/goss/goss-command.yaml”, in your compose file you could add the following line in the corresponding service:
volumes:
./configs/odoo14/goss-command.yaml:/goss/goss-command.yaml
Once this is done, running the command “docker-compose up -d” will create a link between the goss.yaml file on your local file system and the container, allowing it to access the configuration specified in that file.
Conclusion
In summary, Goss is a system validation tool that can be used to verify if Docker containers are in a healthy state. It is a very useful tool to automate testing and ensure that containers meet your configuration requirements.
You can use Goss in conjunction with Docker Compose to check the health status of your containers and map a goss.yaml file into a Docker container for greater control over configuration, improved flexibility, and easier development and upgrades.
If you need more information on how to use this tool, we can provide you with resources and assistance to help you implement it in your project effectively. We are ready to provide you with all the help you need to ensure its successful use. If you would like more information, please contact us.