Container (Docker/Podman)
Install
If not on a base Ubuntu image, cat /etc/upstream-release/lsb-release
may give you a result for the release you are on.
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
apt-cache policy docker-ce
sudo apt install -y docker-ce
sudo systemctl status docker
You may want to add your user to the dockre group: sudo usermod -aG docker $USER
followed by exec bash -l
and/or newgrp docker
to take immediate effect.
Portainer
Update
docker stop portainer
docker rm portainer
docker image rm portainer/portainer-ce
docker run -d -p 8000:8000 -p 9000:9000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Run Container without immediate exiting
On container Setup go to Advanced container settings
and select Interactive & TTY
(or just TTY) under Console
.
Next check the Command
, it should read something similar to /bin/sh
or /bin/bash
View Network
podman network ls --format "{{.Name}}: {{range .Subnets}}{{.Subnet}} {{end}}"
Set CPU and Memory Limit
podman machine stop
podman machine set --cpus 2 --memory 2048
podman machine start
podman machine set --cpus 12 --memory 36864 --disk-size 500
If Images are reported as in use, but no container is running
podman ps --all --storage
podman rmi --force _image_id_
View Usage
podman system df
https://docs.podman.io/en/latest/markdown/podman-system-df.1.html
Maintenance
podman image prune -a --filter "until=168h" # One Week
podman system prune --all --force # Whipe everything (fresh start, this make take some time, rebuilding the images)
podman volume prune --filter "label!=keep" # Remove (currently) unused volumes
podman system df -v
podman ps --size
Copy files to/from container from/to host
podman cp <containerId>:/file/path/within/container /host/path/target
View “structure” of container images
podman image history --no-trunc <image_name>
Private-Hub
Setup
podman run registry
To access the Private-Hub without a secure connection (HTTP instead of HTTPS) you need to add an exception for it.
To do this, you need to add the ip to the insecure-registries
. You can do this by editing the file /etc/docker/daemon.json
{
"insecure-registries" : ["<ip_of_your_registry>:5000"]
}
Alternatively you can make the registry accessable via a reverse proxy with TLS. If you are using you own certificates, you need to add the certs for docker to accept the certificate. Setup with TLS/Certificates: https://docs.docker.com/engine/security/certificates/#troubleshooting-tips
/etc/docker/certs.d/
└── my-https.registry.example.com <-- Hostname without port
├── client.cert
├── client.key
└── ca.crt
Docker-Desktop
Settings → Docker Engine → Add "insecure-registries" : ["<ip_of_registry>:5000"]
on same level as builder
.
Linux
Add "insecure-registries" : ["<ip_of_registry>:5000"]
to daemon.json
. Can be located using locate
.
Publish image on Private-Registry
podman tag <image-name> <registry-ip>:5000/<image-name>
podman push <registry-ip>:5000/<image-name>
Action to build and push automatically
View Registry Content
Dockerfile
Note
Example
FROM python:latest
# set the working directory
WORKDIR /app
# install dependencies
COPY ./requirements.txt /app
RUN pip install --no-cache-dir --upgrade -r requirements.txt
# copy the scripts to the folder
COPY . /app
# start the server
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
Build and Run in seperat containers
FROM golang:1-alpine as build
WORKDIR /app
COPY cmd cmd
RUN go build cmd/hello/hello.go
FROM alpine:latest
WORKDIR /app
COPY --from=build /app/hello /app/hello
EXPOSE 8180
ENTRYPOINT ["./hello"]
Basic Commands
Build image from current folder and tag with given name.
podman build -t <tag_name> .
--no-cache
build the image completetly new, takes a lot longer, then building with cache enabled--platform
build the image for the specified plattform (linux/amd64, linux/i386, linux/arm/v5, linux/arm/v6, linux/arm/v7, linux/arm64, linux/ppc64le, linux/s390x) plattform must be available for/in the base image.
Run a already build image (my tag name -t) in a container in interactive (-i) mode.
podman run -i -t <image_name>
-d (Detached mode)
-p (port mapping, could be 8080:80, which would map the port 80 of the container to the port 8080 of the host).
-rm (remove conatiner after exit)
If you need to enter a already running container, check the Container ID with podman ps
and than run the following command.
podman exec -it <mycontainer> bash
as root
podman exec -u 0 -it <mycontainer> bash
Get logs from (stopped/exited) container
podman logs -t <container-name>
Use podman-compose to run app with “shared filesystem” (use volumes in docker-compose.yaml file to map a path on the host system with a path in the container)
podman-compose run app # or
podman-compose up --build
Example docker-compose.yaml:
services:
app:
build: .
container_name: <just_give_it_a_name>
command: /bin/sh
ports:
- 8080:80
volumes:
- .:/app
Command to list all containers, including failed / crashed containers:
podman ps -a
podman logs <container-id>
podman exec -it <container-id> bash
Run Cron in Container
Install
If not on a base Ubuntu image, cat /etc/upstream-release/lsb-release
may give you a result for the release you are on.
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
apt-cache policy docker-ce
sudo apt install -y docker-ce
sudo systemctl status docker
You may want to add your user to the dockre group: sudo usermod -aG docker $USER
followed by exec bash -l
and/or newgrp docker
to take immediate effect.
Portainer
Update
docker stop portainer
docker rm portainer
docker image rm portainer/portainer-ce
docker run -d -p 8000:8000 -p 9000:9000 -p 9443:9443 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Run Container without immediate exiting
On container Setup go to Advanced container settings
and select Interactive & TTY
(or just TTY) under Console
.
Next check the Command
, it should read something similar to /bin/sh
or /bin/bash
Maintenance
podman image prune -a --filter "until=168h" # One Week
podman system prune --all --force # Whipe everything (fresh start, this make take some time, rebuilding the images)
podman volume prune --filter "label!=keep" # Remove (currently) unused volumes
podman system df -v
podman ps --size
Copy files to/from container from/to host
podman cp <containerId>:/file/path/within/container /host/path/target
Private-Hub
Setup
docker run registry
To access the Private-Hub without a secure connection (HTTP instead of HTTPS) you need to add an exception for it.
To do this, you need to add the ip to the insecure-registries
. You can do this by editing the file /etc/docker/daemon.json
{
"insecure-registries" : ["<ip_of_your_registry>:5000"]
}
Alternatively you can make the registry accessable via a reverse proxy with TLS. If you are using you own certificates, you need to add the certs for docker to accept the certificate. Setup with TLS/Certificates: https://docs.docker.com/engine/security/certificates/#troubleshooting-tips
/etc/docker/certs.d/
└── my-https.registry.example.com <-- Hostname without port
├── client.cert
├── client.key
└── ca.crt
Docker-Desktop
Settings → Docker Engine → Add "insecure-registries" : ["<ip_of_registry>:5000"]
on same level as builder
.
Linux
Add "insecure-registries" : ["<ip_of_registry>:5000"]
to daemon.json
. Can be located using locate
.
Publish image on Private-Registry
docker tag <image-name> <registry-ip>:5000/<image-name>
docker push <registry-ip>:5000/<image-name>
Action to build and push automatically
View Registry Content
Dockerfile
Note
Example
FROM python:latest
# set the working directory
WORKDIR /app
# install dependencies
COPY ./requirements.txt /app
RUN pip install --no-cache-dir --upgrade -r requirements.txt
# copy the scripts to the folder
COPY . /app
# start the server
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
Comments
RUN echo 'This one gets printed'
# RUN echo 'This one does not'
Build and Run in seperat containers
FROM golang:1-alpine as build
WORKDIR /app
COPY cmd cmd
RUN go build cmd/hello/hello.go
FROM alpine:latest
WORKDIR /app
COPY --from=build /app/hello /app/hello
EXPOSE 8180
ENTRYPOINT ["./hello"]
Basic Commands
Build image from current folder and tag with given name.
docker build -t <tag_name> .
--no-cache
build the image completetly new, takes a lot longer, then building with cache enabled--platform
build the image for the specified plattform (linux/amd64, linux/i386, linux/arm/v5, linux/arm/v6, linux/arm/v7, linux/arm64, linux/ppc64le, linux/s390x) plattform must be available for/in the base image.
Run a already build image (my tag name -t) in a container in interactive (-i) mode.
docker run -i -t <image_name>
-d (Detached mode)
-p (port mapping, could be 8080:80, which would map the port 80 of the container to the port 8080 of the host).
-rm (remove conatiner after exit)
If you need to enter a already running container, check the Container ID with docker ps
and than run the following command.
docker exec -it <mycontainer> bash
as root
docker exec -u 0 -it <mycontainer> bash
Get logs from (stopped/exited) container
docker logs -t <container-name>
Use docker-compose to run app with “shared filesystem” (use volumes in docker-compose.yaml file to map a path on the host system with a path in the container)
docker-compose run app # or
docker-compose up --build
Example docker-compose.yaml:
services:
app:
build: .
container_name: <just_give_it_a_name>
command: /bin/sh
ports:
- 8080:80
volumes:
- .:/app
Command to list all containers, including failed / crashed containers:
docker ps -a
docker logs <container-id>
docker exec -it <container-id> bash
Run Cron in Container
Create a file with the cron infos:
# must be ended with a new line "LF" (Unix) and not "CRLF" (Windows)
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.
*/5 * * * * /usr/bin/sh /example-scheduled-task.sh
Next, change your Dockerfile
to install cron and register your crontab (example for Debian-based image):
RUN apt-get update && apt-get install -y cron
COPY example-crontab /etc/cron.d/example-crontab
RUN chmod 0644 /etc/cron.d/example-crontab
RUN crontab /etc/cron.d/example-crontab
If you can not run ENTRYPOINT ["cron", "-f"]
, because there are other processes that need to be startet, create an init.sh
and run that instead on startup ENTRYPOINT ["bash", "init.sh"]
.
In the init.sh
insert the start command for crontab and any furter commands you need.
service cron start
<further commands>
Dump MySQL Database from Container
If you have the root-password set in an environmental variable (MYSQL_ROOT_PASSWORD) you can simply run the following command.
docker exec <your-mysql-container> sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > <path-on-your-host-system>/all-databases.sql
Mount CIFS within a container
- docker run …
–cap-add SYS_ADMIN –cap-add DAC_READ_SEARCH
Common Hickups
If you get the Error
init.sh not found
, make sure to use LF instead of CRLF (Linux vs Windows)
NGINX Reverse-Proxy
Usefull Containers
- LF” (Unix) and not “CRLF” (Windows)
echo “Hello world” >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file. */5 * * * * /usr/bin/sh /example-scheduled-task.sh
Next, change your Dockerfile
to install cron and register your crontab (example for Debian-based image):
RUN apt-get update && apt-get install -y cron
COPY example-crontab /etc/cron.d/example-crontab
RUN chmod 0644 /etc/cron.d/example-crontab
RUN crontab /etc/cron.d/example-crontab
If you can not run ENTRYPOINT ["cron", "-f"]
, because there are other processes that need to be startet, create an init.sh
and run that instead on startup ENTRYPOINT ["bash", "init.sh"]
.
In the init.sh
insert the start command for crontab and any furter commands you need.
service cron start
<further commands>
Dump MySQL Database from Container
If you have the root-password set in an environmental variable (MYSQL_ROOT_PASSWORD) you can simply run the following command.
podman exec <your-mysql-container> sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > <path-on-your-host-system>/all-databases.sql
Create Multi Architecture Image/Manifest
podman build --arch=linux/amd64 -t <user>/<image_name>:v0.1-linux_amd64 .
podman build --arch=linux/arm64 -t <user>/<image_name>:v0.1-linux_arm64 .
podman manifest create <user>/<image_name>:v0.1 <user>/<image_name>:v0.1-linux_arm64 <user>/<image_name>:v0.1-linux_amd64
podman manifest push <user>/<image_name>:v0.1
Mount CIFS within a container
docker run ... \
--cap-add SYS_ADMIN \
--cap-add DAC_READ_SEARCH \
Common Hickups
If you get the Error
init.sh not found
, make sure to use LF instead of CRLF (Linux vs Windows)
Comments