A “container” is a virtually isolated environment. An “image” is formed from multiple layer of commands.
Analogy : An “image” is like the concept of Class from OOP - a blueprint/recipe of what will be. A “container” on the other hand, is like an Object - an instance of Class, or the dish made from a recipe. Obviously, there can be multiple “containers” for same “image”.
Start docker service
systemctl start docker.service
Start now & enable automatic startup on login
systemctl enable --now docker.service
Seek help
docker [command] help
docker <command> [subcommand] --help
Deploy a container
docker run <image-name> [<command>]
with following options:
to get the rest of the options possible, run
docker run --help
Show deployed containers
docker ps [-a for all]
Execute a command in deployed container
docker exec [-it for interactive tty] <container-id> <command>
Stop a container
docker stop <container-id>
Remove a container
docker rm <container-id>
Force stop & remove a container
docker rm -f <container-id>
Pull an image
docker pull <image-name>
Show all images
docker images
Remove an image
docker rm <image-name> [or <image-id> for unnamed images]
Build an image
docker build -t [<image-namespace>/]<new-image-name>[:<image-tag>] .
assuming current directory contains Dockerfile.
Create a named volume
docker volume create <some-name>
List all volumes
docker volume ls
Use host’s network interface (reduces NAT latency)
docker run ... --net=host ...
When mounting volumes “${PWD}” works, “${pwd}” doesn’t. Keep env var case sensitivity in mind.
Can get instance properties of containers (eg ip) as by runnings inspect
docker inspect my-container
Add current user to docker group (to avoid typing ‘sudo’ on every docker command); recommended only on trusted machines.
sudo gpasswd -a $USER docker
To access localhost (outside container), use ip address of bridge interface
ip addr show docker0
To Change default logger and data-root directory, add following to /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"data-root": "/mnt/volume/docker"
}
sudo aa-remove-unknown
It turned out that AppArmor service was messing up with Docker. AppArmor (or “Application Armor”) is a Linux kernel security module that allows the system administrator to restrict programs’ capabilities with per-program profiles.
Dockers require a linux kernel to work, so it works like a virtual machine on Mac.
brew install --cask docker
but docker desktop is not opensource (or fully free).Following dockerfile uses nginx:alpine image to serve static data over 8000
# nginx state for serving content
FROM nginx:1.21-alpine
# Set working directory to nginx asset directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy static assets over
COPY ./static ./
Build the image:
docker build -t static-serve .
Start a container
docker run -p 8000:80 static-serve
Btw, this is all an alternative to:
python -m http.server
Also see multistage builds to reduce image size, if that is a concern. See how-to-use-the-official-nginx-docker-image
For smallest possible image size for static serve, see smallest-docker-image-static-website
docker save <image> | gzip | DOCKER_HOST=ssh://user@remotehost docker load