Docker and Docker Compose have greatly influenced the way I build, test, ship, and run applications. While Docker allows you to package applications into containers, Docker Compose enables you to define and manage multi-container applications. In this article we’ll explore the concepts of context and additional_contexts in Docker Compose, explaining their roles and how to leverage them effectively in your Docker workflows.
While sitting down to write this article, I realized that I’ve never properly introduced “Docker” technology on this blog and much less, “Docker Compose”, although we’ve covered so many associated topics in the past. So before we get to contexts and additional contexts, I’ll give a brief introduction to what the two pieces of related techonology are.
What’s Docker?
Docker is an open-source platform designed to automate the deployment, scaling, and management of applications using containerization. Containers allow developers to package an application with all its dependencies into a standardized unit for software development. This ensures that the application runs reliably in different computing environments.
And What’s Docker Compose?
While Docker excels at running individual containers, modern applications often consist of multiple interconnected services. Docker Compose is a tool that simplifies the process of managing multi-container applications. It allows you to define services, networks, and volumes in a single YAML file, making it easier to run complex applications with a single command.
What’s the Difference between Docker and Docker Compose?
Scope of Management:
- Docker: Focuses on building and running individual containers.
- Docker Compose: Manages multi-container applications defined in a docker-compose.yml file.
Configuration:
- Docker: Uses Dockerfiles and command-line arguments to configure containers.
- Docker Compose: Uses a YAML file to define multiple services, networks, and volumes.
Commands:
- Docker: Requires separate commands for each container.
- Docker Compose: Provides simplified commands (docker-compose up, docker-compose down) to manage all services collectively.
Benefits of Using Docker Compose
- Simplified Management: Control multiple services using a single configuration file.
- Consistent Environments: Ensure all developers and environments use the same configurations.
- Network Automation: Automatically sets up communication between services without manual network configuration.
- Scalability: Easily scale services up or down with minimal effort.
Understanding the context
Now, with all that introduction out of the way, in Docker, the build context refers to the set of files and directories accessible to the Docker engine when building an image. In Docker Compose, the context is specified within the build section of a service definition.
services: web: build: context: . dockerfile: Dockerfile
• context: Specifies the directory to use as the build context. The . indicates the current directory.
• dockerfile: (Optional) Specifies the path to the Dockerfile relative to the context.
Importance of context
The context determines what files are available during the build process. It’s crucial because Docker sends the entire context directory to the Docker daemon, which can impact build performance if the context is large.
The Need for Multiple Contexts
In complex applications, you might need to access files from directories outside the main build context. This requirement poses challenges:
- Monolithic Contexts: Including everything in a single context can lead to bloated and inefficient builds.
- Security Concerns: Exposing unnecessary files increases the risk of unintentionally including sensitive data in your image.
Introducing additional_contexts
To address these challenges, Docker introduced the concept of additional_contexts. additional_contexts allows you to specify multiple contexts, enabling more granular control over the files available during the build.
services: app: build: context: . dockerfile: Dockerfile additional_contexts: othercontext: ../other
• additional_contexts: A mapping of context names to their respective paths.
• othercontext: The name assigned to the additional context, used within the Dockerfile.
Additional Contexts in the Real World
As with most other articles on this blog, this entry came from a real-world experience. I was woking on an Dockerfile that needed access to a particular file, tucked away in my Users
directory within Windows, far away from the application code repository structure. How do I access that one file from some place foreign on my filesystem without setting the context to my entire hard drive? Additional Contexts come to the resuce!
First my docker-compose file:
my-service: Context: ../../../ dockerfile: MyApp/Some/Folder/Structure/my.dockerfile additional_contexts: # We need this additional context to copy the user-level file into the container. user: ~/ my-other-service: ...
Now in my Dockerfile:
WORKDIR /my-app COPY ["MyApp/Some/Other/Folder/package.json", "./"] COPY ["MyApp/Some/Other/Folder/yarn.lock", "./"] # Now let's copy over that special file from the "Users" directory COPY --from=user special.txt /to/some/place/in/my/container RUN other things ...
Best Practices
- Minimize Context Size: Keep your build contexts as small as possible to improve build performance.
- Use .dockerignore: Exclude unnecessary files from your context using a .dockerignore file.
- Secure Sensitive Data: Avoid including sensitive information in your contexts.
Closing Thoughts
Understanding and effectively using context and additional_contexts in Docker Compose can significantly optimize your Docker builds. By leveraging multiple contexts, you gain finer control over the files included in your build process, leading to more efficient and secure Docker images.