Introduction
Using Docker, we can distribute our applications much more quickly and easily on local Linux, Windows or any cloud server without complicated setup. Deployment with Docker can save us a ton of time, particularly for Python Machine Learning applications that need to preinstall numerous libraries or tools.
In this post, I will write a simple Flask web service application and build this application to a Docker image. You will learn how to write the dockerfile, build the Docker image, save and load the Docker image.
1. Prepare Sample Python Code
The sample Python code provided below shows how to launch a Flask web service. You can launch the application by executing the command python3 app.py
or python3 app.py --name your-name
, and view the webpage on http://127.0.0.1:5000/ and http://127.0.0.1:5000/hello.
# app.py
import sys
from gevent.pywsgi import WSGIServer
from flask import Flask, jsonify, request
from flask_cors import CORS
app = Flask(__name__)
@app.route('/')
def index():
return "Hi from " + name + " in index page"
@app.route('/hello')
def hello():
return jsonify({'message': 'Hi from ' + name + ' in hello page'})
if __name__ == '__main__':
name = 'Jacob'
if (len(sys.argv) > 2 and sys.argv[1] == "--name"):
name = sys.argv[2]
CORS(app, resources=r'/*')
http_server = WSGIServer(('0.0.0.0', 5000), app)
http_server.serve_forever()
2. Define Dependencies Requirements File
List down all the libraries in your Python project and write them in a text file with name requirements.txt
. The requirements file for the above sample application shoud be:
# requirements.txt
flask==20.0.2
flask_cors==3.0.8
gevent==1.5.0
3. Write Dockerfile
Before writing Dockerfile, make sure you have installed Docker Engine on your machine. Dockerfile is an instruction manual that guide Docker Engine how to build the required environment for the application to run on. The file name is Dockerfile
.
The directory structure should be like this:
├── project/
│ ├── app.py
│ ├── requirements.txt
│ └── Dockerfile
Here is the Dockerfile for the sample application:
# Dockerfile
FROM python:3.8-slim-bullseye
COPY . /code/
# it equals to
# COPY app.py /code/
# COPY requirements.txt /code/
WORKDIR /code
RUN /usr/local/bin/pip3 install -r /code/requirements.txt && rm -r /root/.cache/pip
EXPOSE 5000
CMD ["python3", "app.py"]
Let me explain some points:
FROM
must be the first instruction of Dockefile, it lets you define what base image you want to use.python:3.8-slim-bullseye
has smaller image size thanpython:3.8-bullseye
.COPY . /code/
means that copy ALL files in the directory/project/
of your machine to the directory/code/
of the Docker image.WORKDIR
sets the working directory for the application in the Docker image.RUN
is used to run Linux command, just like we type command in command line of Linux OS. If you have many commands to run, try to useRUN command_1 && command_2 && command_3 && ...
instead of usingRUN
separately. Because each separateRUN
instruction will build one layer,RUN command_1 && command_2 && command_3 && ...
requires one layer only, which save building time and reduce image size.- You should write an instruction to clean the cache or downloaded file/package after downloading or installing (apt install, pip install…).
- Add
\
at end-of-line to change to a newline, add#
at start-of-line to add comments in Dockerfile.
4. Build the Docker Image
We can start to build the Docker image using the following command:
$ cd project
$ docker build -t myApp:v1.0 .
-t myApp:v1.0
is used to tag the image with a name and version number..
in the end indicates the current directory, which is the path of the Dockerfile.
After building, you can check the new Docker image with command docker images
.
5. Run the Application with Docker
Run the application container with default name:
$ docker run -p 5000:5000 -it myApp:v1.0
Or run the application container with custom name argument:
$ docker run -p 5000:5000 -it myApp:v1.0 python3 app.py --name your-custom-name
Now you can view the webpage on http://127.0.0.1:5000/ and http://127.0.0.1:5000/hello.
Save and Load Local Image
Sometimes project requires us to use the Docker image in the machine/server without internet, we can save the Docker image to a tar file and copy it to another machine to load.
Save the image (not container) in the development machine:
# operaton in development machine
# myApp:v1.0 is the image tag
$ docker save -o myApp.tar myApp:v1.0
You will see myApp.tar in the current directory of development machine, then copy it to production machine to load.
# operaton in production machine
$ docker load -i myApp.tar
Now you can check the loaded Docker image with command docker images
.
You can also use docker export
and docker import
command to export and import container (not image).
Notes: The image file saved using
docker save
is a little bigger than the file exported usingdocker export
.docker import
can rename the new image,docker load
can NOT rename the new image.docker save
can pack multiple images to one file,docker export
can not do it. The image usingdocker export
loses history and meta data, but the image usingdocker save
keeps all the history.docker export
is usually used to create base image.
You can now give it a try!