Welcome back! In the previous lesson, you learned the basics of Docker Compose and how to write a docker-compose.yml
file to manage multi-container applications. This time, you'll take a deeper dive into more advanced features, focusing on volumes and networks. These components are crucial in Docker Compose as they enable persistent storage for your data and seamless communication between your containers. By the end of this lesson, you should feel confident about configuring persistent storage and network connections for your services.
In Docker Compose, managing volumes is handled efficiently within the docker-compose.yml
file. We can configure both bind mounts and named volumes directly in the file, simplifying your application’s data management.
Bind Mounts in Compose:
- We can set up bind mounts by specifying the host directory path and the target path inside the container directly in our
docker-compose.yml
. This setup lets us map portions of the host filesystem into containers effortlessly.
Named Volumes in Compose:
- With Docker Compose, we can easily define and create named volumes under the
volumes:
section. Docker Compose takes care of their creation and management, providing us with reliable data persistence and portability between different host environments.
By leveraging Docker Compose, we can simplify the configuration of volumes. It is generally recommended to handle volume definitions directly in the docker-compose.yml
file to take advantage of automated volume management and ensure consistent deployments. This approach makes our applications more robust and adaptable to various deployment scenarios.
Let's enhance our docker-compose.yml
file by incorporating both a bind mount and a named volume to manage our application's data efficiently. We'll set a bind mount for the web
service to seamlessly synchronize files between the host and the container, and a named volume for the db
service to guarantee persistent storage.
YAML1version: '3' 2 3services: 4 web: 5 image: nginx 6 ports: 7 - "8080:80" 8 volumes: 9 - ./webdata:/var/www/html # Mount the local directory 'webdata' to the container's /var/www/html 10 11 db: 12 image: mysql 13 environment: 14 MYSQL_ROOT_PASSWORD: abcd1234 15 volumes: 16 - dbdata:/var/lib/mysql # Use a named volume 'dbdata' to persist data in /var/lib/mysql 17 18volumes: 19 dbdata: # Define a named volume 'dbdata'
-
Web Service (Bind Mount):
- In the
volumes
key of theweb
service, we set up a bind mount by linking thewebdata
directory on the host to/var/www/html
inside the container. - This means that any changes you make to the files in the
webdata
directory will automatically appear in the container, allowing for easy updates to the web content you are developing.
- In the
-
DB Service (Named Volume):
- For the
db
service, we declared a named volume calleddbdata
in thevolumes
key at the bottom of the file. - This volume is used within the
db
service to store MySQL data at/var/lib/mysql
, ensuring your database data is saved permanently even if the container stops or is deleted.
- For the
We achieve efficient data management by using a bind mount for quick file synchronization in the web
service, and a named volume for persistent data storage in the db
service.
After setting up volumes in your docker-compose.yml
file and running your services, you can list all the volumes that Docker has created using the command docker volume ls
.
When you run this command, you'll see an output similar to:
Plain text1DRIVER VOLUME NAME 2local filesystem_dbdata
This output indicates that Docker has created a named volume called filesystem_dbdata
of type local
for your db
service. The prefix filesystem_
is automatically added to the volume name based on the project directory name, allowing you to identify which volumes are associated with specific projects.
Networks in Docker Compose facilitate communication between your containers. By default, Docker Compose creates a single shared default network for all services defined in a docker-compose.yml
file. This default network allows your services to discover and communicate with each other effortlessly without exposing all ports to the host machine. Containers within the same network can access each other using service names as DNS addresses.
However, you can achieve more granular control over connectivity and isolation by defining custom networks or connecting to existing Docker networks. Custom networks let you specify which services should communicate and which should remain isolated, enhancing security and organization. You can assign services to as many networks as needed—whether they are newly created or pre-existing—giving you flexibility in managing interactions among your application components. This ensures that certain services can connect while others are restricted, offering a more controlled and secure container environment.
Let's examine how to configure networks in your docker-compose.yml
file. In our example, we set up a custom network named appnet
to link the web
and db
services.
YAML1version: '3' 2 3services: 4 web: 5 image: nginx 6 ports: 7 - "8080:80" 8 volumes: 9 - ./webdata:/var/www/html 10 networks: 11 - appnet # Connect the 'db' service to the 'appnet' network 12 13 db: 14 image: mysql 15 environment: 16 MYSQL_ROOT_PASSWORD: abcd1234 17 volumes: 18 - dbdata:/var/lib/mysql 19 networks: 20 - appnet # Connect the 'db' service to the 'appnet' network 21 22volumes: 23 dbdata: 24 25networks: 26 appnet: # Define a custom bridge network 'appnet'
Here, the networks
key at the file's bottom defines appnet
, forming an isolated communication channel for the web
and db
services. By specifying appnet
under each service, you ensure both can easily communicate while keeping them isolated from other services that aren't connected to this network.
Similar to how volumes are managed, Docker automatically creates networks when you define them in your docker-compose.yml
file. To view the networks Docker has created, you can use the command docker network ls
.
Running this command will produce an output like:
Plain text1NETWORK ID NAME DRIVER SCOPE 2096219fa32eb bridge bridge local 353851b7115bb filesystem_appnet bridge local 47d2083ec882b host host local 5754d23fac575 none null local
In this output, you can see a network named filesystem_appnet
with the bridge
driver. The network name filesystem_appnet
includes the prefix filesystem_
, which is derived from the project directory name, assisting you in identifying networks specific to your project. This ensures that the web
and db
services can communicate within the isolated network environment you configured.
In this lesson, you explored the advanced features of Docker Compose, focusing on the critical role of volumes and networks. You learned how volumes can ensure data persistence, whether through bind mounts or named volumes. Additionally, you discovered how custom networks can regulate communication between your containerized services. As you move to the practice exercises, apply these concepts to develop robust applications with Docker Compose. Mastering these skills will pave the way for efficient application deployment and management in containerized environments.