Development with Pod
During development, it is recommended that contributors
load dependencies from the same container image and
mount the source code as a volume.
The reasoning here is
to avoid different behaviour caused by the use of different versions of the dependencies and
to avoid the time costly process of create new container image.
Workflow
Build the container image as described in Building Images.
Run a pod as described in Pod with Volume.
Rebuild the container image as described in Building Images.
Delete and recreate the pod as described in Pod with Volume.
Example
Important
The commands are run from the root of the project.
Given the following Dockerfile
FROM docker.io/alpine:3.21.3
RUN apk add --no-cache \
python3 \
py3-pip \
py3-virtualenv
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN python3 -m pip install \
Flask==3.1.0
WORKDIR /var/app
EXPOSE 5000
ENTRYPOINT [ \
"flask", \
"run", \
"--host", \
"0.0.0.0", \
"--port", \
"5000", \
"--reload", \
"--debugger" \
]
running
podman build \
--tag my-tutorial/my-flask-app:dev \
.
creates a container image named my-tutorial/my-flask-app:dev that has Flask installed.
Given the following Kubernetes manifest file
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-5.3.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
labels:
app: flask
name: flask
spec:
containers:
- image: my-tutorial/my-flask-app:dev
name: flask
ports:
- containerPort: 5000
hostPort: 5000
volumeMounts:
- mountPath: /var/app
name: flask-src
volumes:
- hostPath:
# This is the path in the host machine running Kubernetes or Podman.
# When using WSL2, the Windows C disk is mounted into /mnt/c.
path: ./src
type: Directory
name: flask-src
running
podman kube play ./play.yml
creates a pod named flask with a container named flask running the image my-tutorial/my-flask-app:dev with a volume mounted.
http://localhost:5000/ should show
No module named ‘requests’
The Dockerfile can be modified to provide the library requests like in
--- /home/docs/checkouts/readthedocs.org/user_builds/rse-podman-tutorial/checkouts/latest/source/examples/flask0/Dockerfile
+++ /home/docs/checkouts/readthedocs.org/user_builds/rse-podman-tutorial/checkouts/latest/source/examples/flask1/Dockerfile
@@ -9,7 +9,8 @@
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN python3 -m pip install \
- Flask==3.1.0
+ Flask==3.1.0 \
+ requests==2.32.3
WORKDIR /var/app
Running
podman build \
--tag my-tutorial/my-flask-app:dev \
.
replaces the container image named my-tutorial/my-flask-app:dev with a new container image that has Flask and the library requests installed.
And running
podman kube play --replace ./play.yml
replaces the pod named flask with a container named flask running the new image my-tutorial/my-flask-app:dev, now with the library requests installed, with a volume mounted.
http://localhost:5000/ should show
Hello, World! Let’s read …
Project Structure
Podman can automatically match the container from the Kubernetes manifest file with the Dockerfile if the following project structure is followed.
my-project/
├── .git
├── play.yaml
└── server
└── Dockerfile
and play.yaml includes
apiVersion: v1
kind: Pod
metadata:
...
spec:
containers:
- name: container
image: server
...
Run
podman kube play --build ./play.yml
is equivalent to run
podman build \
--tag server \
./server
followed by
podman kube play ./play.yml