Docker notes
Here are some notes and tips collected for docker during last years.
It is better to check most recent docs on docker installation on the official site as they changed several times
during the last years and now they are inclined to promote Docker Desktop for every platform.
Ubuntu
Add current user to docker group (the group should be created during the installation process)
sudo usermod -aG docker $USER
Check user groups
groups $USER
Restart Docker
sudo service docker restart
Login into Docker’s group
newgrp docker
Mac OS
The --net=host option doesn’t work on macOS
There are special host names inside containers:
docker.for.mac.host.internal
docker.for.mac.localhost
This can be used, for example, to communicate between DB and backend containers as localhost isn’t available
on macOS inside containers.
Docker commands
Test Docker
docker run --rm hello-world
Start a service
docker run --name SOME_NAME --env-file=ENV_FILE --net=host -dp 127.0.0.1:OUTER_PORT:INNER_PORT CONTEINER
--net=host is required if one container should reach another via localhost:port.
If -p is used without a local address like 127.0.0.0 it will be bound to 0.0.0.0 which could be a security issue.
Any network service inside a docker container must be served on 0.0.0.0 to be available outside the container.
Example: start Swagger
docker run --name swagger-editor -dp 0.0.0.0:8080:8080 swaggerapi/swagger-editor
Print container names only
docker ps -a --format "{{.Names}}"
Print container IDs only
doocker ps -a -q
Clean none containers
docker rmi -f $(docker images -f "dangling=true" -q)
It is possible to set LABEL inside a Dockerfile and filter by it
docker image prune --filter label=SOME_LABEL
NOTE: Consider to use docker build --rm this should remove intermediate containers
Copy files from/into a docker container
docker cp SOME_CONTEINER:/path/to/file LOCAL_FILE_NAME
docker cp LOCAL_FILE_NAME SOME_CONTEINER:/path/to/file
List volumes and clean them
docker volume ls
docker volume prune
Clean Docker images
docker rmi $(docker images | grep '^<none>' | awk '{print $3}')
Run something untrusted in Docker
docker run --rm -it -v $(PWD)/untrustedprogram:/untrustedprogram:ro ubuntu:latest
Set Docker limits for build
docker build --cpu-period=100000 --cpu-quota=50000 --memory=1024m -t $PROJECT:$VERSION -f Dockerfile .
Fix a terminal inside a container
Sometimes something could be mis-configured inside a container and things like nano can’t work.
This should be executed inside the container.
export TERM=xterm
Databases oneliners
NOTE: No volumes so they all are ephemeral
PostgresSQL
docker run --name postgres -e POSTGRES_PASSWORD=password -dp 5432:5432 postgres:alpine
docker run --name postgres -e POSTGRES_PASSWORD=password -dp 127.0.0.1:5432:5432 postgres:alpine
docker exec -it postgres psql -U postgres
docker logs -f postgres
MySQL\MariaDB
docker run --name mariadb -e MYSQL_ROOT_PASSWORD=password -dp 127.0.0.1:3306:3306 mariadb
docker exec -it mariadb mysql -p
docker logs -f mariadb
Redis
docker run --name redis -dp 127.0.0.1:6379:6379 redis:alpine
docker exec -it redis redis-cli
docker logs -f redis
MongoDB
NOTE: Security isn’t enabled by default
docker run --name mongodb -dp 127.0.0.1:27017:27017 mongo
docker exec -it mongodb mongo
docker exec -it mongodb mongo admin
docker logs -f mongodb
Multi-Stage Build container example
FROM golang as compiler
RUN CGO_ENABLED=0 go get -a -ldflags '-s' \
github.com/adriaandejonge/helloworld FROM scratch
COPY --from=compiler /go/bin/helloworld .
EXPOSE 8080
CMD ["./helloworld"]
Docker rootless and read-only container example
FROM alpine:3.15.0
# docker build -t alpine .
# docker run -it --name alpine -d alpine
# docker run -it --name alpine -d --read-only alpine
# docker exec -it alpine sh
# docker exec -it -u root alpine sh
RUN addgroup -S alpine
RUN adduser -G alpine -S alpine
USER alpine
CMD sleep infinity
Docker .gitignore
When utilizing a custom Dockerfile name, the associated .dockerignore file should be named to match the custom Dockerfile name, followed by .dockerignore.
For example, if the custom Dockerfile is named Dockerfile.dev, the corresponding ignore file should be named Dockerfile.dev.dockerignore.
When initiating a Docker build with a custom Dockerfile using the -f flag (like, docker build -f Dockerfile.dev .), Docker will first search for an ignore
file with the specific naming convention Dockerfile.dev.dockerignore. If this specific file is not found, Docker will then fall back to using a standard
.dockerignore file if one exists in the build context. This allows for tailored exclusion rules for different build environments or purposes while maintaining
a clear association between the Dockerfile and its ignore rules.
Multistage Dockerfile
FROM python:3.12 AS builder
RUN pip install -r requirements.txt
COPY . /app
FROM python:3.12 AS tests
COPY --from=builder /app /app
CMD ["pytest", "-vv"]
FROM python:3.12 AS service
COPY --from=builder /app /app
CMD ["python", "app.py"]
This way it is possible to build separate images from different stages by using the --target flag:
# Build only the 'service' stage (default, also `--target service` can be used)
docker build -t my-service .
# Build only the 'tests' stage as a separate image
docker build -t my-tests --target tests .
# Build only the 'builder' stage as a separate image
docker build -t my-builder --target builder .
NOTE: docker-compose also supports this by using target: attribute.