Programming inside Containers
By: Reuben Sinha
Tags: Programming, Flask, Docker, Containers

Step 1. Create Environment inside Image

Build a base image called custom-env-image containing required dependencies for the application using a Dockerfile.

#Using base python image

FROM python:3.10.0a2-slim-buster #Changing to project directory inside container

WORKDIR /project #Exposing flask's default port

EXPOSE 5000 #Installing flask library

RUN pip install flask==1.1.2 #Command to execute flask app when container is created.

CMD [“python”, “app.py”]

Additionally, I have also included a CMD instruction to execute the flask application when the container runs.

Step 2. Write some code / Clone code from a repository

The code for a minimal flask application is displayed below. Though robbed of complexity, it can be considered as an example for an existing project, which needs to be extended with some additional code.

#Path: /home/user/project/app.py from flask import Flask app = Flask(__name__)

def hello():

return ‘Hello, world!’ @app .route(‘/’)def hello():return ‘Hello, world!’ if __name__ == “__main__”:

app.run(host=”0.0.0.0", debug=True)

Step 3. Run container with bind mount volume

In step 1, the development environment was compacted into a base image, which can be effortlessly run to create a container with all required libraries for the application.

Remember! Containers are ephemeral, and immutable. Any modifications made within them, will be futile and destroyed when it is removed. For this reason, the code must be detached from the short-lived container using persistent storage which can be achieved with Bind Mounts.

docker container run \

--name web-app \

--volume /home/user/project/:/project \

--publish 5000:5000 \

--detach custom-env-image

Step 4. Check the application

Let’s have a peek at the application in its current state. Since, the container has been published in port 5000, it should be accessible from the browser.

Application output prior to modification

Step 5. Modify the application, build on it!

Instead of returning “Hello World”, let’s modify the application to return the html document shown bellow.

<!--#Path: /home/user/project/templates/page.html--> <html>

<head>

<title>Message</title>

</head>

<body>

<h1>hi, welcome to the website </h1>

</body>

</html>

Make corresponding changes to the flask application, to return page.html

#Path of flask app /home/user/project/app.py

#Path of html document /home/user/project/templates/page.html from flask import Flask app = Flask(__name__)

def hello():

#Lets render a html page instead of "Hello, world!"

return render_template('page.html') @app .route(‘/’)def hello():#Lets render a html page instead of "Hello, world!"return render_template('page.html') if __name__ == “__main__”:

app.run(host=”0.0.0.0", debug=True)

The application gets automatically updated in the browser after a refresh, without having to re-run the container.

Make changes in code, and it runs on the fly!

Step 6. Adding additional Libraries

Seldom does an entire python web application require only the flask library. Installing additional libraries is simple, and can be accomplished by creating a new base image from the old base image. As an example, requests library has been included in the new Dockerfile to create a new base image.

#Using earlier image as base image

FROM custom-env-image #Installing requests library

RUN pip install requests==2.25.0

(Bonus) Step 7. Handling multiple components of a project

Suppose the project includes additional components such as a database, proxy or API services. Then each component’s environment must be compacted inside separate images with bind mounts if required, allowing us to run them as separate containers using docker-compose.