Python app MySQL containerization using Docker

Vaishnavi Piyush Kand
11 min readDec 31, 2023

--

Photo by Rubaitul Azad on Unsplash

Docker is an open source platform which helps you to build, deploy and run your containers without worrying about any dependencies.

Docker compose is a tool where you can work with multiple containers which are defined in YAML file.

I am demonstrating a simple project in which the python app is connecting to the database to insert the data. The python app is dockerized. Let’s start step by step.

Firstly, let’s start by creating a YAML file called docker-compose.yml in which we will create one container for the docker image MySQL.

version: '3'

services:
db-mysql:
image: mysql:latest
container_name: "test-mysql-db"
environment:
MYSQL_ROOT_USER: "root"
MYSQL_ROOT_PASSWORD: "password"
MYSQL_DATABASE: "db"
MYSQL_PASSWORD: "password"
MYSQL_ROOT_HOST: "%"
ports:
- "3306:3306"
healthcheck:
test: mysql --user=root --password=password -e 'show databases'

Run the docker-compose.yml file using the command: docker-compose up — build

Now, we need to check if the mysql database db is created. To check this, we can use MySQL workbench where host field will take localhost value, port will be 3306 (This 3306 is the value mentioned on the left hand side in the ports mapping.), user will be root and password will be password. If the connection is successful, let’s move onto the next step and create the python file.

Create the file called requirements.txt in which python packages required for the project are mentioned.

pymysql
cryptography

Create a folder scripts and python file dbclass.py inside the folder where we will write the class to connect to the database and create table and implement insert_data() function.

import pymysql

class DBClass:
def __init__(self):
self.connection = pymysql.connect(user='root',password='password',host='test-mysql-db',database='db')
print("Connection to database successful....")
self.cursor = self.connection.cursor()


def create_table_if_not_exists(self):
query = "create table if not exists test_table(id int, s_name text);"

try:
self.cursor.execute(query)

except Exception as e:
print(e)

else:
print("Table created successfully....")


def insert_data(self, data:tuple):
query = "insert into test_table(id, s_name) values (%s, '%s')" %data
print(query)

try:
self.cursor.execute(query)
self.connection.commit()

except Exception as e:
print(e)

else:
print("Data inserted successfully...")

Let’s write main.py in the folder scripts to use the class DBClass.

from dbclass import DBClass

def main():
dBClass = DBClass()

dBClass.create_table_if_not_exists()

dBClass.insert_data((1, "Vaishnavi"))

dBClass.insert_data((2, "Bhakti"))

dBClass.insert_data((3, "Vipra"))

if __name__ == "__main__":
main()

Now, let’s modify docker-compose.yml.

version: '3'

services:
app:
container_name: myapp
build:
context: .
dockerfile: Dockerfile
depends_on:
db-mysql:
condition: service_healthy

db-mysql:
image: mysql:latest
container_name: "test-mysql-db"
# restart: always
environment:
MYSQL_ROOT_USER: "root"
MYSQL_ROOT_PASSWORD: "password"
MYSQL_DATABASE: "db"
MYSQL_PASSWORD: "password"
MYSQL_ROOT_HOST: "%"
ports:
- "3306:3306"
healthcheck:
test: mysql --user=root --password=password -e 'show databases'

In the YAML file, there are two services: one is the python app and another one is MySQL. The python app app is dependent on the service db-mysql.

The python app will not start until the MySQL container runs properly and error free. For this there is the health check condition added and the test for the health check.

The python app is using the Dockerfile which contains the definition for myapp container.

FROM python:latest

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

COPY . .

CMD ["python", "./scripts/main.py"]

We are now ready to run our docker-compose.yml file.

C:\Users\docker-mysql-python-demo>docker-compose up --build
[+] Building 4.5s (9/9) FINISHED docker:default
=> [app internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [app internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 189B 0.0s
=> [app internal] load metadata for docker.io/library/python:latest 3.7s
=> [app 1/4] FROM docker.io/library/python:latest@sha256:3733015cdd1bd7d9a0b9fe21a925b608de82131aa4f3d397e465a1fcb545d36f 0.0s
=> [app internal] load build context 0.0s
=> => transferring context: 853B 0.0s
=> CACHED [app 2/4] COPY requirements.txt requirements.txt 0.0s
=> CACHED [app 3/4] RUN pip install -r requirements.txt 0.0s
=> [app 4/4] COPY . . 0.1s
=> [app] exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:5394880e6bdb594903daf14205622bfb00c46a1f7e7d80a84e873706e1df19ca 0.0s
=> => naming to docker.io/library/docker-mysql-python-demo-app 0.0s
[+] Running 3/3
✔ Network docker-mysql-python-demo_default Created 0.2s
✔ Container test-mysql-db Created 0.3s
✔ Container myapp Created 0.4s
Attaching to myapp, test-mysql-db
test-mysql-db | 2023-12-31 16:45:31+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
test-mysql-db | 2023-12-31 16:45:32+00:00 [Warn] [Entrypoint]: MYSQL_PASSWORD specified, but missing MYSQL_USER; MYSQL_PASSWORD will be ignored
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Initializing database files
test-mysql-db | 2023-12-31T16:45:32.834734Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
test-mysql-db | 2023-12-31T16:45:32.838858Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:32.839097Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.2.0) initializing of server in progress as process 81
test-mysql-db | 2023-12-31T16:45:32.855746Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:33.805471Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:37.111583Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
test-mysql-db | 2023-12-31T16:45:43.730594Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.
test-mysql-db | 2023-12-31 16:45:43+00:00 [Note] [Entrypoint]: Database files initialized
test-mysql-db | 2023-12-31 16:45:43+00:00 [Note] [Entrypoint]: Starting temporary server
test-mysql-db | 2023-12-31T16:45:43.886448Z 0 [System] [MY-015015] [Server] MySQL Server - start.
test-mysql-db | 2023-12-31T16:45:44.247580Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:44.251229Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 125
test-mysql-db | 2023-12-31T16:45:44.288028Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:44.592878Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:45.237954Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
test-mysql-db | 2023-12-31T16:45:45.238051Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
test-mysql-db | 2023-12-31T16:45:45.245795Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
test-mysql-db | 2023-12-31T16:45:45.303078Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock
test-mysql-db | 2023-12-31T16:45:45.303669Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 0 MySQL Community Server - GPL.
test-mysql-db | 2023-12-31T16:45:45.310591Z 0 [System] [MY-015016] [Server] MySQL Server - end.
test-mysql-db | 2023-12-31 16:45:45+00:00 [Note] [Entrypoint]: Temporary server started.
test-mysql-db | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
test-mysql-db | 2023-12-31 16:45:54+00:00 [Note] [Entrypoint]: Creating database db
test-mysql-db |
test-mysql-db | 2023-12-31 16:45:54+00:00 [Note] [Entrypoint]: Stopping temporary server
test-mysql-db | 2023-12-31T16:45:54.769942Z 11 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.2.0).
test-mysql-db | 2023-12-31T16:45:56.309382Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.2.0) MySQL Community Server - GPL.
test-mysql-db | 2023-12-31T16:45:56.318087Z 0 [System] [MY-015016] [Server] MySQL Server - end.
test-mysql-db | 2023-12-31 16:45:56+00:00 [Note] [Entrypoint]: Temporary server stopped
test-mysql-db |
test-mysql-db | 2023-12-31 16:45:56+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
test-mysql-db |
test-mysql-db | 2023-12-31T16:45:56.807145Z 0 [System] [MY-015015] [Server] MySQL Server - start.
test-mysql-db | 2023-12-31T16:45:57.134001Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:57.136844Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 1
test-mysql-db | 2023-12-31T16:45:57.159217Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:57.579381Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:58.154535Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
test-mysql-db | 2023-12-31T16:45:58.154631Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
test-mysql-db | 2023-12-31T16:45:58.163591Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
test-mysql-db | 2023-12-31T16:45:58.225016Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
test-mysql-db | 2023-12-31T16:45:58.225508Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
myapp | Connection to database successful....
myapp | Table created successfully....
myapp | insert into test_table(id, s_name) values (1, 'Vaishnavi')
myapp | Data inserted successfully...
myapp | insert into test_table(id, s_name) values (2, 'Bhakti')
myapp | Data inserted successfully...
myapp | insert into test_table(id, s_name) values (3, 'Vipra')
myapp | Data inserted successfully...
myapp exited with code 0\docker-mysql-python-demo>docker-compose up --build
[+] Building 4.5s (9/9) FINISHED docker:default
=> [app internal] load .dockerignore 0.1s
=> => transferring context: 2B 0.0s
=> [app internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 189B 0.0s
=> [app internal] load metadata for docker.io/library/python:latest 3.7s
=> [app 1/4] FROM docker.io/library/python:latest@sha256:3733015cdd1bd7d9a0b9fe21a925b608de82131aa4f3d397e465a1fcb545d36f 0.0s
=> [app internal] load build context 0.0s
=> => transferring context: 853B 0.0s
=> CACHED [app 2/4] COPY requirements.txt requirements.txt 0.0s
=> CACHED [app 3/4] RUN pip install -r requirements.txt 0.0s
=> [app 4/4] COPY . . 0.1s
=> [app] exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:5394880e6bdb594903daf14205622bfb00c46a1f7e7d80a84e873706e1df19ca 0.0s
=> => naming to docker.io/library/docker-mysql-python-demo-app 0.0s
[+] Running 3/3
✔ Network docker-mysql-python-demo_default Created 0.2s
✔ Container test-mysql-db Created 0.3s
✔ Container myapp Created 0.4s
Attaching to myapp, test-mysql-db
test-mysql-db | 2023-12-31 16:45:31+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
test-mysql-db | 2023-12-31 16:45:32+00:00 [Warn] [Entrypoint]: MYSQL_PASSWORD specified, but missing MYSQL_USER; MYSQL_PASSWORD will be ignored
test-mysql-db | 2023-12-31 16:45:32+00:00 [Note] [Entrypoint]: Initializing database files
test-mysql-db | 2023-12-31T16:45:32.834734Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
test-mysql-db | 2023-12-31T16:45:32.838858Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:32.839097Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.2.0) initializing of server in progress as process 81
test-mysql-db | 2023-12-31T16:45:32.855746Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:33.805471Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:37.111583Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
test-mysql-db | 2023-12-31T16:45:43.730594Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.
test-mysql-db | 2023-12-31 16:45:43+00:00 [Note] [Entrypoint]: Database files initialized
test-mysql-db | 2023-12-31 16:45:43+00:00 [Note] [Entrypoint]: Starting temporary server
test-mysql-db | 2023-12-31T16:45:43.886448Z 0 [System] [MY-015015] [Server] MySQL Server - start.
test-mysql-db | 2023-12-31T16:45:44.247580Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:44.251229Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 125
test-mysql-db | 2023-12-31T16:45:44.288028Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:44.592878Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:45.237954Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
test-mysql-db | 2023-12-31T16:45:45.238051Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
test-mysql-db | 2023-12-31T16:45:45.245795Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
test-mysql-db | 2023-12-31T16:45:45.303078Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock
test-mysql-db | 2023-12-31T16:45:45.303669Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 0 MySQL Community Server - GPL.
test-mysql-db | 2023-12-31T16:45:45.310591Z 0 [System] [MY-015016] [Server] MySQL Server - end.
test-mysql-db | 2023-12-31 16:45:45+00:00 [Note] [Entrypoint]: Temporary server started.
test-mysql-db | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
test-mysql-db | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
test-mysql-db | 2023-12-31 16:45:54+00:00 [Note] [Entrypoint]: Creating database db
test-mysql-db |
test-mysql-db | 2023-12-31 16:45:54+00:00 [Note] [Entrypoint]: Stopping temporary server
test-mysql-db | 2023-12-31T16:45:54.769942Z 11 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.2.0).
test-mysql-db | 2023-12-31T16:45:56.309382Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.2.0) MySQL Community Server - GPL.
test-mysql-db | 2023-12-31T16:45:56.318087Z 0 [System] [MY-015016] [Server] MySQL Server - end.
test-mysql-db | 2023-12-31 16:45:56+00:00 [Note] [Entrypoint]: Temporary server stopped
test-mysql-db |
test-mysql-db | 2023-12-31 16:45:56+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
test-mysql-db |
test-mysql-db | 2023-12-31T16:45:56.807145Z 0 [System] [MY-015015] [Server] MySQL Server - start.
test-mysql-db | 2023-12-31T16:45:57.134001Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
test-mysql-db | 2023-12-31T16:45:57.136844Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 1
test-mysql-db | 2023-12-31T16:45:57.159217Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
test-mysql-db | 2023-12-31T16:45:57.579381Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
test-mysql-db | 2023-12-31T16:45:58.154535Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
test-mysql-db | 2023-12-31T16:45:58.154631Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
test-mysql-db | 2023-12-31T16:45:58.163591Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
test-mysql-db | 2023-12-31T16:45:58.225016Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
test-mysql-db | 2023-12-31T16:45:58.225508Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
myapp | Connection to database successful....
myapp | Table created successfully....
myapp | insert into test_table(id, s_name) values (1, 'Vaishnavi')
myapp | Data inserted successfully...
myapp | insert into test_table(id, s_name) values (2, 'Bhakti')
myapp | Data inserted successfully...
myapp | insert into test_table(id, s_name) values (3, 'Vipra')
myapp | Data inserted successfully...
myapp exited with code 0 0.

You can find the github link to the project here.

I hope this article would be useful for you. Thanks for reading :)

--

--