Table of contents
Task
Create a 'Dockerfile' for a simple web application (e.g. a Node.js or Python app)
Build the image using the Dockerfile and run the container
Verify that the application is working as expected by accessing it in a web browser
Push the image to a public or private repository (e.g. Docker Hub).
How to Set Up the Project?
Requirements
Install Git
Install Docker engine
Clone source code from GitHub
Create VM or EC2 instance for project.
Update repository using
apt update
.
File Structure of Source code,
linux$ sudo apt update
linux$ mkdir projects && cd projects
linux$ mkdir python && cd python
Now, clone GitHub repository,
projects/python$ git clone git@github.com:ojasjawale/flask-app.git
shuhari@debian:~/projects/python/flask-app$ tree .
.
├── app.py
├── README.md
├── requirements.txt
├── static
│ └── css
│ └── styles.css
└── templates
├── api_response.html
└── index.html
3 directories, 6 files
Now, Let's create Dockerfile for our application.
Here is Dockerfile,
# Use the official Python 3.11 image based on Alpine
FROM python:3.11-alpine
# Set the working directory in the container
WORKDIR /app
# Copy the source code into the container
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Run app
CMD ["python", "app.py"]
Breaking down the Dockerfile,
- This line sets the base image to Python 3.11 on Alpine Linux, a lightweight distribution known for its small footprint.
# Use the official Python 3.11 image based on Alpine
FROM python:3.11-alpine
- Sets the working directory inside the container to /app. Basically this directory will have all source code copied from local to container.
# Set the working directory in the container
WORKDIR /app
- Copy all source code from local system to container environment.
# Copy the source code into the container
COPY . /app
- Installs the Python dependencies listed in requirements.txt without caching to ensure the latest versions are fetched.
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
- Specifies the command to run when the container starts, launching the Flask application.
# Run app
CMD ["python", "app.py"]
Build an Docker image from Dockerfile
Building a Docker image is a crucial step in containerizing your Flask application.
It involves packaging your application, along with its dependencies, into a single, portable image.
To build the Docker image, open a terminal and navigate to the directory containing your Dockerfile and application code. Execute the following command,
projects/python/flask-app$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
projects/python/flask-app$ docker build -t flask-app:v1 .
Sending build context to Docker daemon 67.58kB
Step 1/5 : FROM python:3.11-alpine
3.11-alpine: Pulling from library/python
ec99f8b99825: Pull complete
a0aab5935990: Pull complete
0017c34ace6c: Pull complete
704141445f22: Pull complete
7d353c5632ce: Pull complete
Digest: sha256:eb8afe385f10ccc9da8378e8712fea8b26f4ed009648f8afea4518836d8b3ed3
Status: Downloaded newer image for python:3.11-alpine
---> 955947f2ffec
Step 2/5 : WORKDIR /app
---> Running in e4d530eca3f2
Removing intermediate container e4d530eca3f2
---> 5b75e87e74f8
Step 3/5 : COPY . /app
---> c8ed1a5c8154
Step 4/5 : RUN pip install -r requirements.txt
---> Running in 371f833bae6b
Collecting Flask==2.1.1 (from -r requirements.txt (line 1))
Downloading Flask-2.1.1-py3-none-any.whl.metadata (3.9 kB)
Collecting Werkzeug==2.2.2 (from -r requirements.txt (line 2))
Downloading Werkzeug-2.2.2-py3-none-any.whl.metadata (4.4 kB)
Collecting Jinja2>=3.0 (from Flask==2.1.1->-r requirements.txt (line 1))
Downloading jinja2-3.1.4-py3-none-any.whl.metadata (2.6 kB)
Collecting itsdangerous>=2.0 (from Flask==2.1.1->-r requirements.txt (line 1))
Downloading itsdangerous-2.2.0-py3-none-any.whl.metadata (1.9 kB)
Collecting click>=8.0 (from Flask==2.1.1->-r requirements.txt (line 1))
Downloading click-8.1.7-py3-none-any.whl.metadata (3.0 kB)
Collecting MarkupSafe>=2.1.1 (from Werkzeug==2.2.2->-r requirements.txt (line 2))
Downloading MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl.metadata (3.0 kB)
Downloading Flask-2.1.1-py3-none-any.whl (95 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 95.2/95.2 kB 6.5 MB/s eta 0:00:00
Downloading Werkzeug-2.2.2-py3-none-any.whl (232 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 232.7/232.7 kB 12.1 MB/s eta 0:00:00
Downloading click-8.1.7-py3-none-any.whl (97 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 97.9/97.9 kB 6.1 MB/s eta 0:00:00
Downloading itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Downloading jinja2-3.1.4-py3-none-any.whl (133 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 133.3/133.3 kB 7.4 MB/s eta 0:00:00
Downloading MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl (33 kB)
Installing collected packages: MarkupSafe, itsdangerous, click, Werkzeug, Jinja2, Flask
Successfully installed Flask-2.1.1 Jinja2-3.1.4 MarkupSafe-2.1.5 Werkzeug-2.2.2 click-8.1.7 itsdangerous-2.2.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
[notice] A new release of pip is available: 24.0 -> 24.1.2
[notice] To update, run: pip install --upgrade pip
Removing intermediate container 371f833bae6b
---> c80d32562bb2
Step 5/5 : CMD ["python", "app.py"]
---> Running in b8233c6e8082
Removing intermediate container b8233c6e8082
---> 801ca0af339a
Successfully built 801ca0af339a
Successfully tagged flask-app:v1
projects/python/flask-app$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-app v1 801ca0af339a About a minute ago 74.5MB
python 3.11-alpine 955947f2ffec 12 days ago 58.2MB
Breakdown of docker build command,
docker build : This command is use to create docker image from Dockerfile.
-t : This flag allows us to specify tag to an image
flask-app:v1 - This is an image name and tag specified
. (dot) : Means location where Dockerfile is located i.e curent location
Run an Docker image as an container
Once you have successfully built your Docker image, the next step is to run it as a container.
This involves creating an instance of your image, which is a runnable environment for your Flask application.
Execute the following command in the terminal:
projects/python/flask-app$ docker run --name flask -p 5000:5000 flask-app:v1
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://172.17.0.2:5000
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
* Debugger PIN: 120-061-676
Breakdown of docker run command,
docker run : Initiates the container creation process
-d : Run container in detached mode i.e in background mode
--name : Specify container name
-p : Specify port to expose from host port and container port. Here, 5000:5000(Host port : Container port).
flask-app:v1 - Mention image name form which container will be created.
Trying to run flask application on browser
Visit <IP_of_your_server>:host_port. To get our flask application running.
i.e in our case, http://192.168.80.141:5000.
API endpoint logs,
How to stop and delete the container and image
To delete the container first stop said container and then delete,
projects/python/flask-app$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce43bbb24722 flask-app:v1 "python app.py" 9 minutes ago Exited (0) 10 seconds ago flask
To delete image,
projects/python/flask-app$ docker rmi flask-app
Untagged: flask-app:v1
Deleted: sha256:801ca0af339ad55982baedd94cdb89bab670dc27b5cb82d32375ebf7fe2ab814
Deleted: sha256:c80d32562bb25729a87988cf7d373db4dee7669915ef9e567b147dff376eb40a
Deleted: sha256:26f833163e785cf17cdc76ded632ade5075192967dc7d8ed562338219b5cc289
Deleted: sha256:c8ed1a5c81542d1b82e777eca103eb6b3277e46c57e3bfcace80a790ee8b09e1
Deleted: sha256:228ee1ddf222570e53bc1385e56ad1e31465a7c504f856a1682b54f88a7af436
Deleted: sha256:5b75e87e74f8e11d4490b34b17460878b7b1dee06931a822e97a3ce5b8d8d5ac
Deleted: sha256:f06e4fa8099a1f23ec3c121c4d1a391afb430c3d86fd1655942cb822e31528fb
Connect with Me
Follow me for more amazing content :)