Simply put, testing code is a challenging problem. Development teams large and small face several key difficulties that negatively impact both software quality and increase release time:
- Diverse development environments
- Diverse testing configurations
- Local code integration
For your organization to create and deliver high quality software, these problems must be addressed and solved. However, this is much more easily said than done. Developers prefer different operating systems and standardizing configuration can be extremely difficult.
Even strictly defining a test harness provides no guarantee that unit tests behave the same way on every system. How many times have you heard a developer say “well, it runs on my computer?” Even integrating your local test code can be difficult, depending on your testing and deployment strategy.
Standardize Applications with Docker
If you haven’t heard of Docker before, check out What is Docker? and Building Applications with Dockerfiles. In a nutshell, Docker lets you package an application and deploy it identically across all of your platforms.
When you deploy your applications this way, you ensure that every instance of your application running in any environment is identical. But Docker provides significantly more power than just application standardization and deployment.
Docker Compose: For Local Development and Testing
Docker Compose is a tool that enables you to describe your entire application using a single, lightweight configuration file. You explicitly define each component using the Docker Compose DSL. Any developer can then launch the application, and it will run the same regardless of environment.
These applications will be deployed as a set of Docker containers. As an example, let’s look at the docker-compose.yml
file describing WordPress, the most popular content management system for blogging.
version: '3' services: db: image: mysql:5.7 volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on: - db image: wordpress:latest ports: - "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress volumes: db_data:
Without understanding the syntax or structure of Docker Compose files, we can clearly see that there are 2 “services” created: “db” and “wordpress.” The db service represents the database that our WordPress site will use. This database service is built using MySQL 5.7 and sets the basic login credentials.
The “wordpress” service runs the latest version of WordPress. It publishes container port 80 to external port 8000 (meaning we can access WordPress on port 8000 locally). It also uses the database described in the “db” service (line 23).
Rapidly Create Development Environments
With Docker Compose, you explicitly describe how your application is deployed. Modern applications are comprised of several individual components, so this naturally fits into the Docker Compose paradigm.
When you describe your applications this way, you can rapidly create identical development environments. To bring up your development environment, you need only provide your engineers the docker-compose.yml
file that describes the application.
After that, each developer executes docker-compose up –d
. That’s it, the application is up, and the developer can now edit code.
This is extremely attractive for large team projects. Instead of a System Administrator provisioning systems with the correct software, developers can start their environments in seconds.
Of course, sharing these environments and test results with others is trickier, which is one of the reasons Codefresh provides dev and test environments built in.
Standardize Testing Configuration
Now that you can rapidly create identical development environments for all of your team members, you can do the same for your test harness. Unfortunately, development environments are inherently different from test harnesses.
Development environments include a myriad of tools not necessary for test environments. Classically running these two side-by-side on the same hardware can negatively affect unit and integration tests. For example, the addition of extra software packages in one environment can hide problems during install scripts in others.
Because of this, you will need a separate configuration for your test environment. This is easily achieved by creating an additional Docker Compose file describing your application’s test harness. It lets you spin up two distinct environments which will decrease problems associated by mixing the two.
You can even run development and test environments side-by-side by default because Docker will isolate the networks that each application uses.
Easily Integrate Local Code
Now that we can rapidly allow developers to create development environments and also bring up isolated test environments, we need to help them easily integrate their code changes. Docker Compose makes this process extremely easy by default.
If we look back at the Docker Compose description of WordPress, we can see that in the database service, there is an entry for “volumes” (lines 6-7). The “volumes” section in a Docker Compose file lets you insert local code into your Docker containers. This allows developers to inject your local code branch into your official test harness, and test only those components.
When you design your test environment’s Docker Compose file, you get to choose which version of each software that is run. For example, in our WordPress docker-compose.yml
above, we explicitly choose MySQL version 5.7 and the most recent version of WordPress.
Instead, you can use the most recent release candidate, the most recent stable build, or even the current production software. This enables your developers to test their software with the right build to support your deployment needs. It also makes building test harnesses within feature branches trivial.
Integrate Docker Compose with Continuous Integration / Continuous Deployment
Now that you can use Docker and Docker Compose to effectively test your code locally, it’s time to integrate with CI/CD. Most CI/CD systems support Docker as a plugin or add-on. However, implementing your organization’s build process using these systems can be very expensive in terms of time. CI/CD is supposed to streamline your organization’s testing process, not induce significant engineering effort.
Codefresh is the only Docker native CI/CD solution built on Kubernetes in the market. Our pipelines build your Docker images directly from Dockerfiles, execute tests against your software, and deploy images to any Docker registry. In addition, Codefresh supports Docker Compose through compositions. This enables your developers to use the same exact testing configuration as your CI/CD pipelines, reducing software bugs and speeding up your release cycle.
Do you already have a CI/CD process set up, or do you want to implement one now? Sign up for Codefresh and see what all of the hype is about (best of all- it’s free!). With Docker-native CI/CD pipelines that support Docker Compose applications by default, you can build your first pipeline in less than 5 minutes.