- Run the app interactively inside an Ubuntu container to enumerate the exact installation and runtime steps.
- Convert those verified steps into a Dockerfile.
- Build, inspect, and run the image from the host.
Goals
- Verify the Flask app runs inside a container.
- Capture the steps required to install dependencies and run the app.
- Convert the manual steps to a reproducible Dockerfile and build the image.
- Run the container and expose the application port to the host.
Overview (manual process)
- Start an Ubuntu container and open a shell.
- Update the apt package index and install Flask for Python 3.
- Create or copy the application source code inside the container.
- Set the
FLASK_APPenvironment variable to point to the application file. - Run the Flask development server binding to all interfaces (
0.0.0.0). - Verify the app is reachable from the host using a port mapping.
Manual run (verify the app works)
Start an interactive Ubuntu container:/opt/app.py (use cat or an editor):
- http://localhost:5000/ → “Welcome!”
- http://localhost:5000/how-are-you → “I am good, how about you?”
When installing packages interactively you may encounter debconf prompts (timezone, etc.). When building images, set
DEBIAN_FRONTEND=noninteractive in the Dockerfile to avoid interactive prompts. This lesson shows that approach.Converting manual steps into a Dockerfile
Key considerations when writing the Dockerfile:- Combine
apt-get updateandapt-get installin a singleRUNinstruction to keep image layers smaller and avoid stale apt caches. - Use
ENV DEBIAN_FRONTEND=noninteractiveto prevent interactive package configuration prompts during build. - Use the exec form (
["cmd", "arg"]) forENTRYPOINTorCMDto ensure proper signal handling and avoid shell parsing issues.
Dockerfile with the following contents:
What each Dockerfile line does
Build the Docker image
From the directory containingDockerfile and app.py, build and tag the image webapp:
Run the container and expose the port
If you run the container without mapping ports, the app runs inside the container but is not reachable from the host. Map container port5000 to host port 5000:
Useful commands (quick reference)
Callouts and best-practice notes
The Dockerfile shown reduces interactive prompts during build via
DEBIAN_FRONTEND=noninteractive, and keeps image layers smaller by combining apt-get update and apt-get install in a single RUN and clearing apt lists. For production, avoid Flask’s built-in development server — use a production WSGI server like Gunicorn and consider an official Python or Alpine-based image to reduce final image size. See Flask docs and Gunicorn.The Flask built-in server is for development only. Before using containers in production, replace the development server with a production-ready WSGI server, apply container security best practices, and minimize the image footprint.
Next steps
- Replace Flask’s built-in server with a production WSGI server (e.g., Gunicorn) and update the Dockerfile
ENTRYPOINTaccordingly. - Use a smaller base image (for example,
python:3-slimor an Alpine-based image) to reduce image size. - Add a
.dockerignorefile to keep unnecessary files out of the build context. - Review Docker best practices: Dockerfile reference and Docker documentation.