Docker
Docker
Docker delivers software in packages called containers. It’s main use is to kill the excuse “it runs on my computer” because if the software is ran on a docker container then it runs on every computer (if you can install docker on the new computer :)).
The main two components of docker are it’s server and client. Both are just software but they have different purposes. The docker server runs as a background process and waits for instructions. It’s main purpose is to create, delete, modify, stop docker containers (programs that are being run on it’s own isolated environment). The docker client is a command line software that we use as users. It’s main purpose is to help us request changes to the containers to the docker server, like requesting to spin up a docker container.
Docker Image
A docker image can be seen as a class in OOP (Object Oriented Programming). Docker images can be built via a Dockerfile file which contains the instructions to build such an image.
Images are made of multiple layers. These layers are instructions that are used to build the image. Each layer, except the last one is read only. The last layer is defined as the container layer which wraps all the other instructions. This layer is only created once the image is instantiated and any modification to the container is going to be applied to the last layer.
When a container is deleted only the container layer is deleted (last layer) while the image remains unchanged. This way multiple containers can use the same image but have different interactions and changes without duplication of the previous layers of the image.
Docker Hub
Docker Hub is a public registry, it’s like GitHub but for sharing docker images. It contains public and private repositories.
Commands
Below there is a series of useful commands that I’ll probably forget and instead of googling them I can access them whenever I want on my website.
Basic Commands
How to run a container. This will create a new “instance” of the image
docker run <image>
Look at the running containers
docker ps
Look at all the containers
docker ps -a
Run container and drop to shell
docker run -it <image>
docker run --interactive --tty <image>
Run container in the background (de-attach)
docker run -d <image>
Container restart settings
docker run --restart (always|no|on-failure[:maxretries]|unless-stopped) <image>
Remove container when exited
docker run --rm <image>
Provide a nickname to a container
docker run --name <name> <image>
How to start a stopped container (instance)
docker start <container>
Run a command against a container
docker exec <container> <command>
Drop into the container shell. Note that the shell must be available in the image OS. For example, for alpine the default one is ash
but for ubuntu it is bash
docker exec -it <container> <shell>
Copy / move files from and to the container.
docker cp <source> <container>:<destination>
docker cp <container>:<source> <destination>
View container information
docker inspect <container>
Create a container image
docker commint <container> <name>
Map container port to host server
docker run -p <host_port>:<container_port> <container>
Run a container de-attach exposing a port with a name
docker run -dt -p <local-port>:<docker-port> --name <container-name> <image-name>
Get an image from docker hub
docker pull <image>
Look at the images you have locally
docker image ls
Remove an image
docker image rm <image-name>
Remove images without at least one container associated to them
docker image prune -a
Get information about an image
docker image inspect <image-name>
Log in to the Docker hub
docker loging --username=<username>
Tag an image
docker tag <image> <username>/<repo>:<tag>
Push image to docker hub
docker push <username>/<repo-name>
Log out of Docker hub
docker logout
Build a Dockerfile image
docker build <dockerfile-path> <name>
Example of Dockerfile
FROM alpine:3.13
RUN apk upgrade
RUN apk add nginx
COPY files/default.conf /etc/nginx/conf.d/default.conf
RUN mkdir -p /var/www/html
WORKDIR /var/www/html
COPY --chown=nginx:nginx /files/html/ .
EXPOSE 80
CMD [ "nginx", "-g", "pid /tmp/nginx.pid; daemon off;" ]
Delete a container once it finished running
docker container run --rm <container-name>
Remove all stopped containers. The -f
flag is to force it and do not prompt for confirmation.
docker container prune -f
Exposing a port of the container
docker container run -d --expose <port-number> <image-name>
Look at the exposed ports of a container
docker container port <container-name>
Start a container with a command
docker container run <image-name> <command>
Executing a command on a container
docker container exec -it <container-name> <command>
Show the logs of a container
docker container logs <container-name>
Show the logs of all the containers in a service
docker service logs <service-name>
Note: Logs need to be output to stdout
and stderr
. For example (nginx):
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
Networking
List of networks
docker network ls
Get detailed information of a network
docker network inspect <network-name>
Create a new network
docker network create <network-name>
Delete a network
docker network rm <network-name>
Delete all unused networks
docker network prune
Adding a container to a network
docker network connect <network-name> <container-name>
Removing a container from a network
docker network disconnect <network-name> <container-name>
Create a network with a subnet and gateway
docker network create --subnet <subnet> --gateway <gateway> <network-name>
docker network create --subnet <subnet> --gateway <gateway> --ip=range=<ip_range> --driver=<driver> <network-name>
Volumes
Docker containers have two types of data. The first one is non-persistent data which is tied to the life-cycle of the container. The persistent type of data in docker is called volumes and it isn’t tied to the life-cycle of the container.
List all volumes on a host
docker volume ls
Create a volume
docker volume create <volume-name>
Inspect a volume
docker volume inspect <volume-name>
Deleting a volume
docker volume rm <volumen-name>
Remove all unused volumes
docker volume prune
Using bind mounts
# With the mount flag
docker container run -d --name <container-name> --mount type=bind,source=<source>,target=<target> <image-name>
# Using the volume flag
docker container run -d --name <container-name> -v <source>:<target> <image-name>
Dockerfile
Dockerfiles are instructions on how to build an image. It has the following instructions.
FROM:
sets the base image.
RUN:
execute any commands.
CMD:
default execution of the container. There can only be one at the end of the dockerfile.
LABEL:
adds metadata to an image.
EXPOSE:
informs docker that the container listens to the specified network ports at runtime.
ENV:
set the environment variable
ADD:
copies new files, directories, or remote file URLs from
WORKDIR:
set the working directory for any RUN
, CMD
, ENTRYPOINT
, COPY
and ADD
instructions that follow it in the Dockerfile.
ARG:
Defines a variable that users can pass at build-time to the builder with the docker build
command using the --build-arg <varname>=<value
flag.
ONBUILD:
Adds a trigger instruction to the image that executes when the image is used as the base for another build.
HEALTHCHECK:
Tells docker how to test a container to check that it is still working.
SHELL:
Allows the default shell used for the shell form of commands to be overridden.
USER:
Specifies the user that is going to run all the commands (RUN
and CMD
)
VOLUME:
Creates a mount point with the specified name and marks it as holding externally mounted volumes from native host or other containers.
Images
Build an image
docker image built -t <image-name>:<tag>
Build an image from a docker repository
docker image build -t <image-name>:<tag> <git-url>\#<branch>
Adding a name and an optional tag
docker image build -t <name>:<tag>
Use the commit hash as the image tag
git log -1 --pretty=%H
Create an image for docker hub
docker image tag <image-name>:<tag> <username>/<image-name>:<tag>
Pushing an image to docker hub
docker image push <username>/<image-name>:<tag>
Show the history of an image
docker image history <image-name>
Export image into a tar file
docker iamge save <image-name> > <filename>.tar
docker image save <image-name> -o <filename>.tar
Loading an image from a tar file
docker image load < <filename>.tar
docker iamge load -i <filename>.tar
docker image load --input <filename>.tar
Container Management
Display running processes on a container
docker container top <container-name>
Display stats of a docker container
docker container stats <container-name>
To make a container auto restart you can do the following with the flags:
- no: do not automatically restart the container (default).
- on-failure: restart the container if exits due to an error.
- always: always restart the container if it stops.
- unless-stopped: similar to always, except that when the container is stopped it is not restarted even after the Dcoker daemon restarts.
docker container run -d --name <container-name> --restart <flag> <image-name>
To get docker events
docker system events
Docker Compose
Create a compose service
docker-compose up -d
List containers created by docker-compose
docker-compose ps
Stop a compose service
docker-compose stop
Start a compose service
docker-compose start
Delete a compose service
docker-compose down
Example of a docker-compose.yml file
version: '3'
services:
app-name:
build:
context: .
args:
- VERSION=v2.0
ports:
- "8081:3000"
environment:
- NODE_ENV=production
Note the following, docker compose has 4 top level keys: version, services, networks and volumes. The version key is mandatory and it’s used to define the compose file format. The compose file format is tied to the docker engine version.
Docker Swarm
Docker Swarm has two major components. The first one is the cluster. This clusters manages one or more Docker nodes. The communication between the nodes is encrypted. The second component is an orchestration engine for creating micro-services.
List all nodes
docker node ls
Inspecting a node
docker node inspect <node-name>
Promoting a worker to a manager
docker node promote <node-name>
Demoting a manager to a worker
docker node demote <node-name>
Removing a node form the swarm
docker node rm -f <node-name>
Have a node leave the swarm
docker swarm leave
Getting the join token
docker swarm join-token <worker|manager>
Have the node rejoin the swarm
docker swarm join --token <token> <private-ip>:2377
Creating a docker service
docker service create -d --name <service-name> -p <host-port>:<container-port> --replicas <number-of-replicas> <image-name> <cmd>
List all services
docker service ls
Inspecting a service
docker service inspect <service-name>
Getting logs for a service
docker service logs <service-name>
List all tasks of a service
docker service ps <service-name>
Scaling a service up and down
docker service scale <service-name>=<replicas-number>
Updating a service
docker service update [options] <service-name>
Creating a overlay network
docker network create -d overlay <network-name>
Creating a service with an overlay network
docker service create -d --name <service-name> \
-p <host-port>:<container-port> \
--replicas <replicas-number> \
<image-name> <cmd>
Adding a service to a network
docker service update --network-add <network-name> <service>
Removing a service from a network
docker service update --network-rm <network-name> <service-name>
Adding plugins
docker plugin install <plugin-name> [options]
Listing plugins
docker plugin ls
Disable a plugin
docker plugin disable <plugin-id>
Delete a plugin
docker plugin rm <plugin-id>
To deploy a whole application one could use stacks and docker-compose
docker stack deploy --compose-file docker-compose.yml <stack-name>
Docker Security
Using a custom seccomp profile
docker contianer run --security-opt seccomp=<profile> <image-name> <cmd>
Dropping capabilities (commands) from a container
docker container run --cap-drop=<command> <image-name> <cmd>
Limiting CPU and Memory
docker container run -it --cpus=<value> --memory=<value> <size> --memory-swap <value> <size> <image-name> <cmd>
Docker Content Trust
Creating a key
docker trust key generate <name>
Importing a key
docker trust key load <pem> --name <name>
Add signer
docker trust signer add --key <pem> <name> <repository>
Remove signer
docker trust signer remove <name> <repository>
Signing an image
docker trust sign <image-name>:<tag>
Docker secrets
Creating a secret using STDIN
STDIN | docker secret create <secret-name>
Creating a secret using a file
docker secret create <name> <file>
List secrets
docker secret ls
Inspecting a secret
docker secret inspect <secret-name>
Using a secret
docker service create --name <service-name> --secret <secret-name> <image-name>
Deleting a secret
docker secret rm <secret-name>