Bootstrap your projects with Docker init
Jérôme Dx
Posted on November 18, 2024
In may 2023, Docker announced a new command line docker init
, that could simplify your life when creating new projects.
It is aimed to quickly generate Dockerfile and Docker-compose file for your projects, following the best practices pushed by the editor himself.
Let's see how it works, with a simple example, running on Flask.
Create the app
Create a my-api.py
file :
#!/usr/bin/python3
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/")
def hello_world():
return "API is running..."
@app.route("/users", methods=["GET"])
def caracters():
return jsonify({
"users": [
"Luke",
"Leia",
"Han",
"Chewi",
"Darth",
"Obi",
]
})
if __name__ == '__main__':
app.run(port=3000, debug=True)
And a requirements.txt
file :
flask>=2.2.2
gunicorn
Generate the files
Execute docker init
and answer the questions.
It will generate you the following files :
Dockerfile
- The instructions to build your image
# syntax=docker/dockerfile:1
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/go/dockerfile-reference/
# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7
ARG PYTHON_VERSION=3.12.4
FROM python:${PYTHON_VERSION}-slim as base
# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1
# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
ARG UID=10001
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
# Leverage a bind mount to requirements.txt to avoid having to copy them into
# into this layer.
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=bind,source=requirements.txt,target=requirements.txt \
python -m pip install -r requirements.txt
# Switch to the non-privileged user to run the application.
USER appuser
# Copy the source code into the container.
COPY . .
# Expose the port that the application listens on.
EXPOSE 3000
# Run the application.
CMD gunicorn 'my-api:app' --bind=0.0.0.0:3000
.dockerignore
- The files you don’t want to copy to your container
# Include any files or directories that you don't want to be copied to your
# container here (e.g., local build artifacts, temporary files, etc.).
#
# For more help, visit the .dockerignore file reference guide at
# https://docs.docker.com/go/build-context-dockerignore/
**/.DS_Store
**/__pycache__
**/.venv
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
README.Docker.md
- The Readme associated to Docker elements
### Building and running your application
When you're ready, start your application by running:
`docker compose up --build`.
Your application will be available at http://localhost:3000.
### Deploying your application to the cloud
First, build your image, e.g.: `docker build -t myapp .`.
If your cloud uses a different CPU architecture than your development
machine (e.g., you are on a Mac M1 and your cloud provider is amd64),
you'll want to build the image for that platform, e.g.:
`docker build --platform=linux/amd64 -t myapp .`.
Then, push it to your registry, e.g. `docker push myregistry.com/myapp`.
Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/)
docs for more detail on building and pushing.
### References
* [Docker's Python guide](https://docs.docker.com/language/python/)
compose.yaml
- The file to execute Docker-compose
# Comments are provided throughout this file to help you get started.
# If you need more help, visit the Docker Compose reference guide at
# https://docs.docker.com/go/compose-spec-reference/
# Here the instructions define your application as a service called "server".
# This service is built from the Dockerfile in the current directory.
# You can add other services your application may depend on here, such as a
# database or a cache. For examples, see the Awesome Compose repository:
# https://github.com/docker/awesome-compose
services:
server:
build:
context: .
ports:
- 3000:3000
# The commented out section below is an example of how to define a PostgreSQL
# database that your application can use. `depends_on` tells Docker Compose to
# start the database before your application. The `db-data` volume persists the
# database data between container restarts. The `db-password` secret is used
# to set the database password. You must create `db/password.txt` and add
# a password of your choosing to it before running `docker compose up`.
# depends_on:
# db:
# condition: service_healthy
# db:
# image: postgres
# restart: always
# user: postgres
# secrets:
# - db-password
# volumes:
# - db-data:/var/lib/postgresql/data
# environment:
# - POSTGRES_DB=example
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
# expose:
# - 5432
# healthcheck:
# test: [ "CMD", "pg_isready" ]
# interval: 10s
# timeout: 5s
# retries: 5
# volumes:
# db-data:
# secrets:
# db-password:
# file: db/password.txt
Now you can launch your app
Directly on your machine :
pip install flask --user
flask --app my-api --debug run -p 3000
With Docker :
docker build -t my-api .
docker run -d -p 3000:3000 --name my-api my-api
With Docker-compose :
docker init
docker compose up --build
What about Podman ?
Nowadays, we can’t talk about Docker without mentioning it’s alternative Podman.
Both provide very similar commands overall, but the Init command is an exception.
Podman-init has a different purpose : it creates a new container from an image and prepares it to run as a Podman container.
Conclusion
Docker-init is a handy little utility integrated into the command-line.
Consider using it when you need to create new projects (or update old ones), it can save you a few precious minutes, while helping you to be compliant by following best practices.
Posted on November 18, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.