Using Docker CLI
Installation
Install the Docker Engine for Linux (Ubuntu) here.
To run Docker as a non-root user
- Create the
docker
group:sudo groupadd docker
- Add your user to the group:
sudo usermod -aG docker $USER
- Logout and back in.
Docker allows the code you write to be run anywhere. While learning Docker isn't always straightforward, it is a crucial technology for modern software development and it worthwhile to learn.
Docker works by using Docker images. These images contain information about the filesystem, code, and dependencies needed to run a program. Images are run in instances called containers, which share the underlying operating system but otherwise entirely isolates the user space (or environment) the code is executed in.
What is a Container?
A container is a running process with a dedicated subset of computer resources that are allocated specifically to that process.
Basics
To build a docker image you need a Dockerfile, this is like a recipe that outlines the steps that are executed to setup the docker image. There are many examples of Dockerfiles online that can be used as templates for a specific project.
To build an image, use the command:
docker build .
# OR a bit more advanced
docker build --tag <name_of_image>:<version> --file foo/Dockerfile .
docker build .
# OR a bit more advanced
docker build --tag <name_of_image>:<version> --file foo/Dockerfile .
In the above command, the -t
argument specifies the tag/name that is given to this image. This argument can be omitted, but it is recommended since it provides information about images on your machine when you run docker images
.
Additionally, if you run this command in the folder with the target Dockerfile, the --file Dockerfile
argument is unnecessary, but this allows for Dockerfiles to be located in different places and with different names.
Finally, the .
at the end of the command defines the build context, any parent directory of the build context won't be accessible inside the Docker image.
To run the docker image after it's been built, use command:
docker run -v $(pwd):/foo -it <name_of_image>:<version>
docker run -v $(pwd):/foo -it <name_of_image>:<version>
This will run the docker image in an interactive session and mount the current directory ($(pwd)
) to the folder /foo in the container (see How to Mount a Local Directory).
How Does this Work? To begin, Docker checks your filesystem for the specified image (e.g. ubuntu:22.04
may be used in place of <name_of_image>
in the above command to run a pre-built Docker image). If the image isn't found locally it checks Docker Hub, a Docker Registry that contains publicly available images. Private registries can also be set up to use private Docker images (see How to Set Up a Private Docker Registry).
Tip
Every time you use the
docker run
command you're creating a new container. This takes up disk space. You can remove containers withdocker rm <ID>
or autoremove when the container is exited by adding--rm
to thedocker run
command.
Important Commands
docker build
Build your docker container --no-cache progress=plain .
: Show progress without cache, good for debugging -t/--tag <docker-id>/<image-name>:<version>
: Tag your docker image so you can refer to it via its tag
docker push
Push the container into your docker registry
docker start -a <id>
Start one or more stopped containers
docker start -a 37a8c # Use `-a` to attach the container to stdin/stdout
docker start -a 37a8c # Use `-a` to attach the container to stdin/stdout
-ia
: Attach container in an interactive session
docker stop <id>
or docker kill <id>
Stop sends SIGTERM, allows for a little bit of clean up. Kill sends SIGKILL, stop immediately.
docker kill nanomq
docker stop nanomq
docker kill nanomq
docker stop nanomq
docker ps
List running containers -a/--all
: Show all containers
docker network ls
List all networks created by docker.
docker images
or docker image ls
List images -a/--all
: List all images
docker logs <id>
docker run
Convenience command for creating and then starting a container -it
: Attach to stdin & stdout of the container's prompt --name <name>
: Give the container a name for easier reference --rm
: Clean up the container after it exits (this is very useful) -d/--detach
: Run docker container in background -v/--volume X:/Y/Z
: Mount a volume from directory X on the host to directory /Y/Z in the container -p/--publish X:Y
: Map port X on the host to port Y in the container --network=host
: Uses the host's network (127.0.0.1) for the container
Overriding default command.
docker run <image> <override-command>
# e.g. open a shell in the container, regardless of the default CMD
docker run -it <image> bash
# e.g.
docker run busybox echo hi there
> hi there
docker run <image> <override-command>
# e.g. open a shell in the container, regardless of the default CMD
docker run -it <image> bash
# e.g.
docker run busybox echo hi there
> hi there
Run vs. create and start
docker run hello-world
# same as
docker create hello-world
> a9dsmd...
docker start -a a9dsmd
docker run hello-world
# same as
docker create hello-world
> a9dsmd...
docker start -a a9dsmd
docker exec
Execute a command in a currently running container.
docker run --name abc redis
docker exec -it abc redis-cli # Add `-it` if you want to bind to the shell
docker run --name abc redis
docker exec -it abc redis-cli # Add `-it` if you want to bind to the shell
Tips 'n Tricks
Attach to a terminal in a running container
docker exec -it <container-id/name> [bash/zsh/sh]
docker exec -it <container-id/name> [bash/zsh/sh]
Creating an Running a web app
Recall, Docker containers are isolated from the underlying OS, this includes network ports. To forward a port from the container to the underlying OS, use the -p
option. For example,
docker run -p 8080:9090 <name_of_image>
docker run -p 8080:9090 <name_of_image>
exposes port 8080 in the Docker container on port 9090 on the host OS.
Removing images, containers, volumes
- Always remove your containers before removing the associated image or volumes.
docker container ls
docker rm <container tag or id>
docker image ls
docker rmi <image tag or id>
docker volume ls
docker volume rm <volume tag or id>
docker volume prune # This can free up lots of disk space
docker system prune # Remove all docker artifacts including containers, images, etc.
docker container ls
docker rm <container tag or id>
docker image ls
docker rmi <image tag or id>
docker volume ls
docker volume rm <volume tag or id>
docker volume prune # This can free up lots of disk space
docker system prune # Remove all docker artifacts including containers, images, etc.
Logging in to docker registry
Reference the docker login
command here
# Option 1
docker login <registry> -p <password> -u <username>
# Option 2 (recommended)
echo $DOCKER_PASSWD | docker login <registry> -u <username> --password-stdin
# Option 1
docker login <registry> -p <password> -u <username>
# Option 2 (recommended)
echo $DOCKER_PASSWD | docker login <registry> -u <username> --password-stdin
Pushing to docker registry
Reference this article for how to build and push Docker images to a registry in CI
# Only available once logged in to the registry
# Ensure you have a build image with the correct tag name
docker build --tag registry.example.com/group/image:version .
docker push registry.example.com/group/image:version
# Only available once logged in to the registry
# Ensure you have a build image with the correct tag name
docker build --tag registry.example.com/group/image:version .
docker push registry.example.com/group/image:version
Remove all docker containers or images
docker container rm -f $(docker container ls -aq)
docker image rm $(docker image ls -aq)
docker container rm -f $(docker container ls -aq)
docker image rm $(docker image ls -aq)
Troubleshooting
If you receive and error like
Error response from daemon: Get "https://registry-1.docker.io/v2/": Get "https://auth.docker.io/token? <REDACTED> : net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Error response from daemon: Get "https://registry-1.docker.io/v2/": Get "https://auth.docker.io/token? <REDACTED> : net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Trying issuing
docker login
docker login
If this doesn't work, try restarting the docker daemons
systemctl restart docker
systemctl restart containerd
systemctl restart docker
systemctl restart containerd
ESSENTIAL RESOURCES
- Setup a Private Docker Registry
- An great primer on setting up a private Docker Registry and Nginx reverse proxy
ADDITIONAL RESOURCES
Understanding Docker Networking
- From inside of a Docker container, how do I connect to localhost of the machine?
- How To Communicate Between Docker Containers Courses
- https://learndocker.online/courses/
- https://www.digitalocean.com/community/tutorials/how-to-share-data-between-the-docker-container-and-the-host
- https://blog.gruntwork.io/a-crash-course-on-docker-34073b9e1833
- https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
- https://docs.docker.com/get-started/09_image_best/
- https://docs.docker.com/develop/dev-best-practices/