Docker
- Installation
- Verify set-up
- Images
- docker system commands
- Containers
- Bridge network
- Logs
- Events
- Other references:
- Sample implementations
- Alternatives to Docker
- Tags
Installation
To check if docker is installed in your computer, try to check for its version: docker --version
. Search for it using sudo pacman -S docker
and install it.
To check if docker-compose is installed in your computer, try to check for its version: docker compose version
. Search for it using sudo pacman -S docker-compose
and install it.
In MacOS, use homebrew for both docker and docker-compose. Use the cask version for docker. If you see this error:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Launch docker desktop, and that usually resolves it.
Verify set-up
In Linux,
If you see this error:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Start the systemctl service
systemctl start docker
To stop docker
systemctl stop docker
To check if docker is running :
sudo service docker status
To check if Docker Client is talking to Docker Daemon and that Docker Daemon is talking to Docker Hub successfully:
docker run hello-world
If you see errors like the ones below:
[explorer436@explorer436-Thinkpad ~]$ docker ps
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied
[explorer436@explorer436-Thinkpad ~]$ docker run hello-world
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create": dial unix /var/run/docker.sock: connect: permission denied.
Reason for this error:
- The Docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The Docker daemon always runs as the root user.
- With the default set-up, you might see an error that says “Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2fvar%2frun%2fdocker.sock/v1.40/containers/json?all=1: dial unix /var/run/docker.sock: connect: permission denied”.
- In this case, change the access permissions on “/var/run/docker.sock” using the command “sudo chmod 666 /var/run/docker.sock”
- https://docs.docker.com/install/linux/linux-postinstall/*manage-docker-as-a-non-root-user
Change the permissions of the files
$ sudo chmod 666 /var/run/docker.sock
See docker run --help
Images
A Docker image is DockerHub is a static template - a set of bytes.
Image is like a class and container is like an object based on that class.
Command | Description |
---|---|
sudo docker search mongodb |
To search for images in docker hub, either use the web interface or use this command |
docker pull mysql or docker pull myimage:1.0 |
To pull an image from a registry (DockerHub) into our machine |
docker tag myimage:1.0 myrepo/myimage:2.0 |
To Retag a local image with a new image name and tag |
docker push myrepo/myimage:2.0 |
To push an image to a registry |
docker image history imageId |
To view the history of a Docker image |
docker image inspect imageId |
To inspect the history of a Docker image |
docker image remove imageId |
To remove a Docker image from local machine |
docker image |
To list all the images that are pulled into the machine from DockerHub |
docker image ls |
List all images that are locally stored with the Docker Engine |
docker image rm alpine:3.4 |
Delete an image from the local image store |
docker build -t myimage:1.0 |
Build an image from the Dockerfile in the current directory and tag the image |
docker system commands
Command | Description |
---|---|
docker system df |
Show docker disk usage, including space reclaimable by pruning |
docker-compose --file docker-compose-kafka-cluster-setup.yml up -d (docker-compose up) |
Command to spin up the cluster from a docker compose file |
docker-compose down |
Shutdown your containers (run docker-compose up to pick up where you left off) |
docker volume prune |
Remove all unused volumes |
docker image prune |
Remove unused images |
docker system prune |
All of the above, in this order: containers, volumes, images |
docker system prune -a |
When there is “not enough space” error from Docker, use this command to clean up the stopped and running containers |
docker exec
Execute a command in a running container
https://docs.docker.com/engine/reference/commandline/exec/
sudo docker exec -it mysql-docker-container bash
sudo docker exec -it <container-name> bash
sudo docker exec -it <container-id> bash
Processes in a container
To display the processes running in a container: docker top containerId
Live stream
To display a live stream of container(s) resource usage statistics: docker stats
Containers
Docker Container
- a running version of the image. For the same image, we can have multiple containers running.
Container commands
Command | Description |
---|---|
docker container ls |
List containers |
docker container list |
(same as above) |
docker container ps |
(same as above) |
docker ps |
(same as above) |
docker ps -a (--all) |
Show both running and stopped containers |
docker container prune |
Remove all stopped containers |
docker container rm -f $(docker ps -aq) |
Delete all running and stopped containers |
Running containers
Run a container from the Alpine version 3.9 image, name the running container “web” and expose port 5000 externally, mapped to port 0 inside the container: docker container run --name web -p 5000:80 alpine:3.9
docker run -p 5000:5000 nameOfTheDockerRepository/nameOfTheApplication
docker run -p {HostPort}:{ContainerPort} nameOfTheDockerRepository/nameOfTheApplication
(docker run is a shortcut for docker container run)
- To list the running containers:
docker container ls
- To list the running and terminated containers:
docker container ls -a
What ports are my containers exposing?
docker port containerId
[explorer436@explorer436-p50-20eqs27p03 hello-world-rest-service]$ docker port 556b
8080/tcp -> 0.0.0.0:8080
8080/tcp -> [::]:8080
Detatched mode
If we want the container to be running in the background, use the -d
option.This way, the terminal is not tied to the lifecycle of the container. Detatched mode: docker run -p 5000:5000 -d nameOfTheDockerRepository/nameOfTheApplication
Stopping containers
To stop a container based on containerId : docker container stop containerId
This will give the application that is running in the container some time to gracefully shut itself down. e.g. close connection pools, close executorService, etc. stop -> SIGTERM -> graceful shutdown
Killing containers
- To kil a container based on containerId :
docker container kill containerId
- To kil a container based on container name :
docker container kill containerName
- To stop all docker containers
docker stop $(docker ps -a -q)
- To remove all docker containers
We can do it using a one-liner:docker container prune or docker rm $(docker ps -a -q)
docker container rm $(docker container ls -aq) -f docker container ls -aq lists container's ids only docker container rm $(..) -f forcibly removes all container's ids
- Kill the container and the application that is running in it right away.
- kill -> SIGKILL -> immediately terminate the process
Pausing containers
- To pause a container:
docker container pause containerId
- To unpause a container:
docker container unpause containerId
Inspect containers
To inspect a container: docker container inspect containerId
Test applications by running curl commands within the container
Launch bash terminal in the container using this: docker exec -it containerId bash
[explorer436@explorer436-p50-20eqs27p03 hello-world-rest-service]$ docker exec -it a9f8 bash
root@explorer436-p50-20eqs27p03:/usr/src/hello-world-rest-service# curl --verbose http://localhost:8080
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 13
< date: Wed, 24 Apr 2024 20:12:09 GMT
<
* Connection #0 to host localhost left intact
Hello, world!
root@explorer436-p50-20eqs27p03:/usr/src/hello-world-rest-service# exit
Errors with port numbers
Connection reset by peer when hitting Docker container
When you start a docker container and test the application using the “Test applications by running curl commands within the container” method, it works. But when you try to test it from the host (either from terminal or from a browser), you see the error:
[explorer436@explorer436-p50-20eqs27p03 hello-world-rest-service]$ curl --verbose http://localhost:8080
* Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.3.0
> Accept: */*
>
* Recv failure: Connection reset by peer
* Closing connection
curl: (56) Recv failure: Connection reset by peer
First, check to see if the server application is configured to only listen to requests coming from its “localhost”. This check depends on the type of server that you’re using. An easy check is to start your container as follows:
docker run --network host -d yourimagename
You don’t need to worry about port mapping since you are using the host network.
Then try to curl from the host machine - either using terminal or from a browser.
curl --verbose http://localhost:8080
If that works, then you’ll just need to review your server listening IP setting.
Reason for the error:
It is an issue with the address(es) the server binds to. Connection reset by peer
usually indicates that one has defined a port mapping for the container that does not point to a listening server.
Connection Reset
to a Docker container usually indicates that you’ve defined a port mapping for the container that does not point to an application.
So, if you’ve defined a mapping of 80:80, check that your process inside the docker instance is in fact running on port 80 (netstat -an|grep LISTEN).
You get a reset as the Docker ‘proxy’ picks up the connection, attempts to connect to the process inside the container, fails, so resets the connection.
How can we see this? Using netstat -tulpn
or netstat -an
[explorer436@explorer436-p50-20eqs27p03 hello-world-rest-service]$ docker exec -it be6f9d bash
root@be6f9de1be34:/usr/src/hello-world-rest-service# netstat -tulpn
bash: netstat: command not found
root@be6f9de1be34:/usr/src/hello-world-rest-service# apt install net-tools
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package net-tools
root@be6f9de1be34:/usr/src/hello-world-rest-service# apt update
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm-updates InRelease [55.4 kB]
Get:3 http://deb.debian.org/debian-security bookworm-security InRelease [48.0 kB]
Get:4 http://deb.debian.org/debian bookworm/main amd64 Packages [8786 kB]
Get:5 http://deb.debian.org/debian bookworm-updates/main amd64 Packages [13.8 kB]
Get:6 http://deb.debian.org/debian-security bookworm-security/main amd64 Packages [155 kB]
Fetched 9209 kB in 2s (4568 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
All packages are up to date.
root@be6f9de1be34:/usr/src/hello-world-rest-service# apt install net-tools
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 243 kB of archives.
After this operation, 1001 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian bookworm/main amd64 net-tools amd64 2.10-0.1 [243 kB]
Fetched 243 kB in 0s (3025 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package net-tools.
(Reading database ... 23248 files and directories currently installed.)
Preparing to unpack .../net-tools_2.10-0.1_amd64.deb ...
Progress: [ 0%] [...........................................................................................................................................................................................................................................]
Unpacking net-tools (2.10-0.1) ...###############################............................................................................................................................................................................................]
Setting up net-tools (2.10-0.1) ...#############################################################################.............................................................................................................................................]
Progress: [ 60%] [#############################################################################################################################################..............................................................................................]
root@be6f9de1be34:/usr/src/hello-world-rest-service# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 7/target/debug/hell
root@be6f9de1be34:/usr/src/hello-world-rest-service# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 3 [ ] STREAM CONNECTED 307714532
unix 3 [ ] STREAM CONNECTED 307714531
root@be6f9de1be34:/usr/src/hello-world-rest-service# netstat -an|grep LISTEN
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
How to fix the error?
One way to fix this is:
Change the configuration in the app. See how the address is configured in the app. Does it have localhost
or 127.0.0.1
as host? If we change it to 0.0.0.0
, it will work. Reason? Without 0.0.0.0
, it was acting only on localhost aka the docker container but not from outside of it.
Make sure you run your service as 0.0.0.0:{port} rather than 127.0.0.1:{port}.
Bridge network
Every container that runs is a part of the bridge network in Docker - it is an internal Docker network. Nobody will be able to access it unless we specifically expose it on to the host system where the container is running.
List the networks
docker network
docker network ls
Logs
To look at logs for a container that is running: docker logs containerId
(you don’t have to type the entire id. A subset of the id will do)
To follow the logs: docker logs -f containerId
Print the last 100 lines of a container’s logs: docker container logs --tail 100 web
Events
To view the events happening in docker: docker events
Other references:
Take a look at the docker-compose files in the following repository for details about setting up multiple containers in the same network:
proof-of-concepts/spring-data-mongodb-rest/