Programming inside Containers
Manager: “Hi Leroy! Welcome to the project. You won’t have to spend half a day to setup the environment in your machine, just clone and run!”
Leroy: “Wha-! Are you serious?”
Unlike the tedious, sometimes daunting task of installing software galore for a project, often with ambiguous or incomplete literature and version incompatibilities, containerisation offers a clean and quick alternative for rapid setup of a functional development environment. Let me present my case with the example of a simple flask application.
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.pyfrom flask import Flaskapp = Flask(__name__)@app.route(‘/’)
return ‘Hello, world!’if __name__ == “__main__”:
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 \
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.
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.
<h1>hi, welcome to the website </h1>
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.htmlfrom flask import Flaskapp = Flask(__name__)@app.route(‘/’)
#Lets render a html page instead of "Hello, world!"
return render_template('page.html')if __name__ == “__main__”:
The application gets automatically updated in the browser after a refresh, without having to re-run the container.
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.
This is a fun little example, presenting a case for programming inside containers. Perhaps infeasible at present, considering the advantages of a normal development environment such as integration with IDEs, convenient debugging and testing tools, which outweigh the characteristic portability of a containerised development environment.
However with proper plan, design and foresight, programming in containers can be achieved, allowing developers to kick-start their work with a simple clone and run.
Best practices for writing Dockerfiles
This document covers recommended best practices and methods for building efficient images. Docker builds images…