Excluding these sections:
- Export / Import / Save / Load
- Docker Hub / Registry
- Overlay networks
- Swarms
Docker Install
Ubuntu / Debian
Docker IO ( Debian/Ubuntu, older ):
apt update
apt install docker.io
docker -v
apt install docker-compose
docker-compose -v
Docker CE (official, newer):
sudo apt update
sudo apt install apt-transport-https ca-certificates curl gnupg
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
Post install:
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker ${USER}
RHEL / Fedora
Fedora install with DNF:
sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest \
docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
RHEL install with YUM:
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest \
docker-latest-logrotate docker-logrotate docker-engine podman runc
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Start / Stop / Run Containers
Create / run a container:
docker run -d ubuntu # start detatched
docker run -tid ubuntu # detatched, STDIN open, allocate pseudo-TTY
docker run -tid --name smelly-hippo ubuntu # name a container
Manage / start / stop container:
docker start smelly-hippo # start
docker stop smelly-hippo # stop
docker kill smelly-hippo # sends SIGKILL, faster than stop
docker rm smelly-hippo # remove
docker rm -f smelly-hippo # force remove, works when already running
docker container start $(docker ps -aq) # start all containers
docker container stop $(docker ps -aq) # stop all containers
docker container rm -f $(docker ps -aq) # Remove all containers, running or stopped
docker container ls # new style command
docker container rm -f smelly-hippo # new style command
Viewing and Inspecting Containers
Show containers:
docker ps # show running containers
docker ps -a # show all containers
Get container info:
docker inspect smelly-hippo # inspect container
docker stats # resourse stats for all containers
docker stats smelly-hippo # resource stats for one container
docker top smelly-hippo # shows processes in a container
docker logs smelly-hippo # container logs
docker events # watch events in real time
docker port smelly-hippo # shows public facing port of container
docker diff smelly-hippo # show changes to a container's file system
Show highest Mem or CPU usage:
# Linux - Sort by 4th column ( mem ):
docker stats --no-stream --format "table {{.Name}}\t{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" | sort -k 4 -h
# MacOS
docker stats --no-stream --format "table {{.Name}}\t{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" | sort -k 9 -n
Connect / login to a container
Just exec a shell if you want a shell:
docker attach smelly-hippo # connect to running container ( main app output )
# container needs to start with -it for detatch to work
# detatch with CTRL-p CTRL-q.
docker exec -it smelly-hippo bash # get shell on host, exit will exit and keep running
Limits
Set limits for CPU, memory, and storage like this:
docker run -tid -c 512 ubuntu # 50% cpu
docker run -tid --cpuset-cpus=0,4,6 ubuntu # use these cpus
docker run -tid -m 300M ubuntu # limit memory
docker create -ti --storage-opt size=120G ubuntu # limit storage, not on aufs
Images
Manage images like this:
docker images # show images
docker history ubuntu # show history of image
docker image rm user1/funny-frog # remove image
docker image remove 113a43faa138 # remove by id
docker image remove user1/funny-frog # remove image
docker rmi user1/funny-frog # remove image
docker rmi $(docker images -q) # remove all images
Commit container to an image:
docker commit smelly-hippo # no repo name
docker commit smelly-hippo test1 # repo name
docker commit smelly-hippo loworbitflux/test1 # repo name
docker commit smelly-hippo loworbitflux/test1:my-update # tagged
docker commit smelly-hippo loworbitflux/test1:v1.2.3 # tagged
Volumes
Manage volumes like this:
docker info | grep -i storage # check storage driver
docker inspect web # look for “Mounts”
docker volume ls # show voluems
docker volume create testvol1 # create a volume
docker volume inspect testvol1 # inspect a volume
docker volume ls -f dangling=true # find dangling ( unused ) volumes
docker volume rm volume1 # remove volume
Running containers with volumes:
docker run -d --name test1 -v /data ubuntu # unamed volume mounted on /data
docker run -d --name test2 -v vol1:/data ubuntu # named volume
docker run -d --name test3 -v /src/data:/data ubuntu # bind mount
docker run -d --name test4 -v /src/data:/data:ro ubuntu # RO
docker run -d --volumes-from test2 --name test5 ubuntu # storage can be shared
docker rm -v test1 # remove container and unnamed volume
Access and sharing parameters:
:ro | for read only |
:z | shared all containers can read/write |
:Z | private, unshared |
/var/lib/docker/overlay2 | Defalt volume storage location on Ubuntu Linux |
Publish / Expose ports
- expose port - set metadata showing this port is used by container ( done in Dockerfile )
- publish / bind port - connect host port and container port
Publishing ports:
docker run -d -p 8080:80 nginx # publish port HOST_PORT:CONTAINER_PORT
docker run -d -p 80 nginx # publish to random "ephemeral" host port
docker run -d -p 8000-9000:80 nginx # publish to range of host ports
docker run -p 8080:80/tcp -p 8080:80/udp nginx # UDP and TCP
docker run -P nginx # publish all exposed ports to ephemeral host ports
docker run -p 127.0.0.1:8080:80 nginx # bind to localhost
docker run -p 192.168.3.231:8080:80 nginx # specific IP
docker run -p 8080:80/udp nginx # UDP
- NOTE - Ports don’t need to be published for inter-container communication on the same network.
Networking
Show and inspect networks:
docker network ls # show networks, bridge is default
docker network inspect bridge # show network details and connected containers
Create Bridge Network, Specify Subnet and Gateway:
docker network create -d bridge my-network
docker network create -d bridge --subnet 172.25.0.0/16 my-network
docker network create --subnet 203.0.113.0/24 --gateway 203.0.113.254 my-network
docker network rm my-network # remove network
Run container, specify network and IP:
docker run -tid --net=my-network --ip=172.25.3.3 --name=test1 ubuntu
Connect / disconnect container with network:
docker network connect net1 test1
docker network connect net1 test2 --ip 172.25.0.102
docker network disconnect net1 test1 # Disconnect container from this network
docker network disconnect -f test1 test2 # Force disconnect
Find container’s IP address:
docker inspect -f '{{json .NetworkSettings.Networks}}' container1
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
Dockerize Applications
mkdir mydockerbuild # Create build dir
cd mydockerbuild # cd into build dir
vi Dockerfile # Edit build instructions
docker build -t mydockerimage . # Build the image (note the dot "." )
docker images # Show images
docker run mydockerimage # Run the new image
Most basic docker file:
FROM ubuntu
RUN apt update
RUN apt install nginx -y
CMD ["/usr/sbin/nginx"]
Bigger docker file:
FROM ubuntu # base image
RUN apt update # run commands while building
RUN apt install nginx -y # run commands while building, new layer, commits results
WORKDIR ~/ # working dir that CMD is run from
CMD echo Hello World! # main command / default application
ENV SERVER_WORKS 4 # set env variable
EXPOSE 8080 # expose a port, not published to the host
LABEL version="1.0" # add metadata
USER 751 # UID (or username) to run as
VOLUME ["/my_files"] # sets up a volume
COPY test relativeDir/ # copies "test" to `WORKDIR`/relativeDir/
COPY test /absoluteDir/ # copies "test" to /absoluteDir/
COPY ssh_config /etc/ssh/ssh_config # copy over a vile
COPY --chown=user1:group1 files* /data/ # also changes ownership
ADD /dir1 /dir2 # like copy but does more ...
Shell vs Executable form:
CMD echo test # shell form, goes through shell, has env vars
CMD ["echo", "test"] # executable form, executed directly, no env vars ( double quotes, not single )
Use ENTRYPOINT and CMD together:
ENTRYPOINT ["echo", "test one"] # can't override this
CMD [“test two”] # can override this part
CMD
- can be overridden
- only used when command line args are missing
- shell form or executable form
ENTRYPOINT
- can’t be ignored or overridden ( with normal args )_
- can still override with “–entrypoint”
- command line args are appended to entry point as args
- shell for or executable form
- default entrypoint: “/bin/sh -c”
Docker Compose
Basic compose commands:
docker compose ps # show
docker compose up # bring everything up
docker compose up -d # detatched / background
docker compose stop # just stops
docker compose down # stop, remove containers
docker compose down --volumes # stop, remove containers, remove data volumes
docker compose watch # watch mode
Basic compose file:
compose.yaml
services:
app:
image: nginx
ports:
- 8080:80
More options:
include:
- infra.yaml
version: '2'
services:
web:
ports:
- "5000:5000"
volumes:
- vol1:/data1
- /opt/data:/deploy/data
- /opt/data:/deploy/data:ro
restart: unless-stopped
environment:
- TEST=1000
redis:
image: "redis:alpine"
Watch, copy in changed files, and rebuild image:
version: '2'
services:
web:
build: .
volumes:
- .:/code
develop:
watch:
- action: sync
path: .
target: /code
- action: rebuild
path: package.json
- NOTE - Compose can also build app if Dockerfile is present.