Hands-on Example of Docker Compose

Search for a command to run...

Python, Golang, Javascript, etc libraries require packaging. It's done to easily distribute code among users thereby avoiding problems in future development. In Python, a library is distributed through the Python Package Index (PyPI), a public hostin...

I want to tell a story of an amazing community called Bioinformatics Community but texts wouldn't be enough. Anyhoo, I blogged about my experience at BCC 2020 on OBF's website. This event was one of my highlights of the summer.

Recently, I needed to combine 2 or more PDF files into one. Merging these PDF files could be due to the company's demand or a need to track all files in one file. In this tutorial, I'd show you how I accomplished this particular task on my machine. T...

GraphQL and Python Series (Expressive Introduction) This is part 1 of an ongoing series to introduce you to using GraphQL and Python. Hopefully, at the end of this series, you will be able to build a GraphQL Backend with Django and Graphene. GraphQL ...
TL;DR This article uses Docker Compose to create and manage multiple container applications. It's entirely hands-on.
Docker has made it easier to develop and package applications in reproducible environments. With Docker, you worry less about the infrastructure of your local machine and that of the production environment and worry more about worry about your code. Although a good product, sometimes when building you would want to run different parts of an application using Docker. What this means is you will create a couple of Dockerfiles and manage them. You orchestrate the containers yourself. This makes maintaining them both hectic and time-consuming.
Docker Compose is a tool used to run many Docker containers representing different parts of an application. To define and configure services (applications) with Compose, you use YAML files. The tool creates, starts, and stops these services that run as Docker containers. Docker Compose is great for rapid prototyping of microservices and continuous integration pipelines.
Let's look at a docker-compose file with MYSQL configurations, call it docker-compose.yml.
services:
mysql:
image: "mysql:8.0"
container_name: mysql
restart: always
ports:
- "3300:3306"
volumes:
- dbdata:/var/lib/mysql/data
environment:
- MYSQL_DATABASE=database
- MYSQL_USER=user
- MYSQL_PASSWORD=password1212
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
volumes:
dbdata:
The above YAML file has some things to note.
mysql is created, and it depends on the mysql:8.0 published image on Docker Hub.Flask microframework is used to interact with the database. To create this, follow the instructions below.
python and change directories into it.app.py that connects with the MYSQL container and processes inputsfrom flask import Flask, render_template, request
import mysql.connector
import json
app = Flask(__name__)
config = {
'host': 'mysql',
'user': 'user',
'password': 'password1212',
'port': '3306',
'database': 'data',
'auth_plugin':'mysql_native_password'
}
connection = mysql.connector.connect(**config)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == "POST":
details = request.form
firstName = details['fname']
lastName = details['lname']
cur = connection.cursor()
cur.execute("INSERT INTO MyUsers(firstName, lastName) \
VALUES (%s, %s)", (firstName, lastName))
mysql.connection.commit()
cur.close()
return 'success'
return render_template('index.html')
requirements.txt that contains the dependencies of the python file.Flask==1.1.2
mysql-connector-python==8.0.21
index.html that accepts inputs from a user.<HTML>
<BODY bgcolor="cyan">
<form method="POST" action="">
<center>
<H1>Enter your details </H1> <br>
First Name <input type = "text" name= "fname" /> <br>
Last Name <input type = "text" name = "lname" /> <br>
<input type = "submit">
</center>
</form>
</BODY>
</HTML>
Dockerfile with the following contentsFROM python:3.6-alpine3.11
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT [ "python", "app.py" ]
python folder and initialize the MYSQL instance by creating a database and a table. To do this, create a file called init.sql and fill up with the followingCREATE DATABASE data;
use data;
CREATE TABLE MyUsers (
firstName VARCHAR(20),
lastName VARCHAR(20),
);
docker-compose.yml file and connect all the pieces. version: "3"
services:
mysql:
image: "mysql:8.0"
container_name: mysql
restart: always
ports:
- "3300:3306"
volumes:
- dbdata:/docker-entrypoint-initdb.d/:ro
environment:
- MYSQL_DATABASE=data
- MYSQL_USER=user
- MYSQL_PASSWORD=password1212
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
app:
container_name: "flask_app"
restart: always
links:
- mysql
build:
context: python
dockerfile: Dockerfile
ports:
- "5000:5000"
volumes:
dbdata:
python and builds a docker image from the Dockerfile in the folder.init.sql file.The project should have the structure below:
├── docker-compose.yml
├── init.sql
└── python
├── app.py
├── Dockerfile
├── index.html
└── requirements.txt
The image below shows the block diagram of the docker-compose file.

To execute the above block, run docker-compose up on your terminal and access the HTML on localhost:5000.
We have seen how Docker Compose works and some basic explanations. Things to note:
.env file insteadGlossary
ephemeral: lasting for a very short time. This means without volumes, data generated and in docker are volatile and will be lost on termination of a container (either a restart or a rebuild).
orchestrate: Container orchestration is the automatic process of managing or scheduling the work of individual containers for applications based on microservices within multiple clusters.
service: A service is a section that defines all the containers used by our application.
3300: The default port for connections should be port 3306, but for easier understanding of where local ports and container ports are in a file, 3300 is used.