- Introduction
- Part I: Getting started
- Install Docker
- After installation, check Docker version
- Download an image from the Docker Hub
- Run a simple echo command in a container using the
alpine
image - Run another command in a Docker container
- Run command in a Docker container that's not installed
- Docker's
hello-world
image - List Docker images
- View running Docker containers
- View all Docker containers (running or not)
- Recap: images and containers
- Part II: Basic interactions with containers
Containers are useful tools for saving the computing environments for running applications and this tutorial provides the bare minimum to get started with them. Written while learning Docker myself, this guide has the quality of naivety that only a real beginner can attain.
If Docker is not installed, you need to install Docker.
At a command prompt type docker -v
:
[~/docker_for_beginners]$ docker -v
sh: docker: command not found
If you get this message then you need to install Docker.
Here you will find the instructions for installing Docker
- on a Mac: Install Docker Desktop for Mac (or alternatively good instructions here). Note that only the newest versions of the Mac OS are supported and you will need at least 4GB of RAM.
- on Windows: Install Docker Desktop on Windows. Requirements: Windows 10 with 64 bit processor and at least 4GB of RAM.
- on Linux: Ubuntu, Centos, etc.
[~/docker_for_beginners]$ docker -v
Docker version 1.13.1, build 07f3374/1.13.1
This is really just to check that Docker is installed.
Docker Hub (https://hub.docker.com) is an online repository of Docker images.
You will need an image to get started with Docker—for this we're going to use Alpine Linux (https://hub.docker.com/_/alpine).
Alpine Linux (Alpine for short) is a minimal Linux image, designed to run from the computer's RAM. Its size is 5MB.
This is off-topic for a beginner's tutorial, but if you're interested in learning more about Alpine Linux you can read an interview with its creator (https://thenewstack.io/alpine-linux-heart-docker/) or the Wikipedia entry for Alpine Linux (https://en.wikipedia.org/wiki/Alpine_Linux).
The main entities in Docker are containers. A container is a piece of software that emulates a complete machine with some pre-installed libraries and code. Containers allow to distribute software applications together with the whole environment they need for running. By packaging an application in a container we can run it on any computer without the need for any special configuration, thus making the application seamlessly portable.
A Docker image (sometimes also called container image) is a file that's essentially a snapshot of a container. Images are created with the build
command, and they'll produce a container when started with run
.
There's a discussion on Stackoverflow that helps clarifying the difference between images and containers: What is the difference between a Docker image and a container?
Some quotes from that discussion:
What is the difference between a Docker image and a container?
And what is a stopped container then? "A stopped container is a cake in the freezer"
In the Docker world, downloading an image is known as pulling an image because to download an image you need to use the command docker pull
followed by the name of the image.
[~/docker_for_beginners]$ docker pull alpine
[~/docker_for_beginners]$ docker container run alpine echo 'Hello World!'
Alternatively, if you prefer to use double quotes, you can type:
[~/docker_for_beginners]$ docker container run alpine echo "Hello World\!"
(note the slash escape character before the exclamation mark)
You should see the string Hello World!
. What has happened behind the scene? Docker created a container from your newly downloaded alpine
image and you ran the command echo 'Hello World!'
inside this container. The result of the command is shown on your terminal.
To show the message-of-the-day (motd) file we run the command cat /etc/motd
inside the container.
[~/docker_for_beginners]$ docker container run alpine cat /etc/motd
Welcome to Alpine!
The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org/>.
You can setup the system with the command: setup-alpine
You may change this message by editing /etc/motd.
If you run a command in a container whose image is not yet installed, the image will be downloaded automatically from the Docker Hub. This is quite a practical feature!
We're going to echo 'Hello World!'
in a centos
container.
[~/docker_for_beginners]$ docker container run centos echo 'Hello World!'
Unable to find image 'centos:latest' locally
Trying to pull repository docker.io/library/centos ...
latest: Pulling from docker.io/library/centos
a02a4930cb5d: Pull complete
Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426
Status: Downloaded newer image for docker.io/centos:latest
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 639 0 639 0 0 612 0 --:--:-- 0:00:01 --:--:-- 612
Hello World!
So, in the previous example, instead of running docker pull alpine
followed by docker container run alpine echo 'Hello World'
we could have just used the latter command. Still, one might also need sometimes to download an image without running it, so it' good to know how to do that.
Docker provides a special hello-world
image that can be called with:
$ docker run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
To show all locally available Docker images use docker images
. These are the images that we have pulled sometime in the past.
[~/docker_for_beginners]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos 7.4.1708 295a0b2bd8ea 2 days ago 197 MB
alpine latest 961769676411 3 weeks ago 5.58MB
docker.io/hello-world latest 4ab4c602aa5e 5 months ago 1.84 kB
List Docker containers with docker container ls
.
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
You might at this point just get an empty list unless you have some running container.
[~/docker_for_beginners]$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e57cbe736396 alpine "echo 'Hello World'" 2 days ago Exited (0) 2 days ago amazing_buck
9edd35220ee7 alpine "ping 8.8.8.8" About a minute ago Exited (0) 2 days ago unruffled_archimedes
e3f28fbfb08f alpine "cat /etc/motd" 2 days ago Exited (0) 2 days ago vibrant_gates
b86e65d14484 hello-world "/hello" 14 minutes ago Exited (0) About a minute ago everent_germain
Note how Docker assigns fantasy names (like the "amazing_buck" or "unruffled_archimedes" above) to new containers. You can assign a name to your containers by using the option --name your-name
when creating them.
In place of docker container ls
(respectively docker container ls -a
) you can also use docker ps
(resp. docker ps -a
). See this discussion on Github on why these two commands are both allowed.
We've defined Docker images and containers and seen how to run simple commands in a Docker container and list all our images and containers.
Here's a list of Docker commands used so far:
how to: | command |
---|---|
check Docker version | docker -v |
download the Linux Alpine image | docker pull alpine |
run a simple echo command | docker container run alpine echo 'Hello World!' |
view the message-of-the-day in alpine | docker container run alpine cat /etc/motd |
print 'Hello World!' in Linux Centos (image is downloaded if not present) | docker container run centos echo 'Hello World!' |
show all locally available images | docker images |
list Docker containers | docker container ls (also: docker ps ) |
view all Docker containers (running or not) | docker container ls -a (also: docker ps -a ) |
Instead of running a Docker container with an interactive shell it is also possible to let a Docker container run as a daemon, which means that the Docker container runs in the background completely detached from your current shell (the option -d
stands for detached).
Let us start a container in daemon mode:
[~/docker_for_beginners]$ docker container run -d alpine ping host.docker.internal
a592973ccb204dbcd142052a89c187cc62b8bc1817a04c02e2f79a7205b8c1f7
Note that we used ping host.docker.internal
to have a command running forever, so that the alpine
container keeps running. host.docker.internal
is the name under which Docker containers identify the address of the host where they're running (localhost
outside the container).
If you now list running containers you should see it
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a592973ccb20 alpine "ping host.docker.in…" 8 seconds ago Up 23 seconds nifty_blackwell
To stop a running container use docker stop
:
[~/docker_for_beginners]$ docker stop nifty_blackwell
nifty_blackwell
Note that you can use either the container's id or name as an argument to stop
.
Check:
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Indeed, the container is no more running.
Note that the option -d
forces the container to run in a separate shell but when the container has no processes running then it stops.
[~/docker_for_beginners]$ docker container run -d alpine
a7a87f89bad8e9a079500feaa337b612b154bbc21bb8b1376d9724005930a5bf
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
To keep the container alive use the run option -i
:
[~/docker_for_beginners]$ docker container run -di alpine
10f7ffbddbb9c2ec3212c22e67bc1b3f56827a02bceb7feb6e81ae52409e7846
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10f7ffbddbb9 alpine "/bin/sh" 3 seconds ago Up 2 seconds hungry_chaplygin
Now the "hungry_chaplygin" alpine container is up even though it has no process running.
To execute a command in a running Docker container use exec
.
[~/docker_for_beginners]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10f7ffbddbb9 alpine "/bin/sh" 10 minutes ago Up 10 minutes hungry_chaplygin
We are going to run a command inside a running alpine container. The command uname -a
shows Linux operating system information.
[~/docker_for_beginners]$ docker exec -it hungry_chaplygin uname -a
Linux 10f7ffbddbb9 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux
Start a shell inside the container, run some commands and exit.
[~/docker_for_beginners]$ docker exec -it hungry_chaplygin /bin/sh
/ # pwd
/
/ # ls -p
bin/ dev/ etc/ home/ lib/ media/ mnt/ opt/ proc/ root/ run/ sbin/ srv/ sys/ tmp/ usr/ var/
/ # whoami
root
/ # exit
Open the file $HOME/.profile
and add this line:
export PS1='\033[31mDOCKER ${HOSTNAME}\e[0m [$(whoami) $(pwd)]# '
This will show "DOCKER" followed by the name of the Docker container in red (here you can find more tips on how to format shell prompts).
[~/docker_for_beginners]$ docker exec -it hungry_chaplygin /bin/sh -l
DOCKER 10f7ffbddbb9 [root /]#
Note: since by default sh
won't read the .profile
file but it will read it only at login, the -l
(login) option is needed.
If you don't need a container anymore, you can delete it as follows:
[~/docker_for_beginners]$ docker container rm <container ID>
Example:
[~/docker_for_beginners]$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e57cbe736396 alpine "echo 'Hello World'" 2 days ago Exited (0) 2 days ago amazing_buck
9edd35220ee7 alpine "ping 8.8.8.8" About a minute ago Exited (0) 2 days ago unruffled_archimedes
e3f28fbfb08f alpine "cat /etc/motd" 2 days ago Exited (0) 2 days ago vibrant_gates
b86e65d14484 hello-world "/hello" 14 minutes ago Exited (0) About a minute ago everent_germain
[~/docker_for_beginners]$ docker container rm e57cbe736396
[~/docker_for_beginners]$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9edd35220ee7 alpine "ping 8.8.8.8" About a minute ago Exited (0) 2 days ago unruffled_archimedes
e3f28fbfb08f alpine "cat /etc/motd" 2 days ago Exited (0) 2 days ago vibrant_gates
b86e65d14484 hello-world "/hello" 14 minutes ago Exited (0) About a minute ago everent_germain
As usual, you can refer to a container by its ID or by its name.
If the container is running, you will get an error message when trying to remove it. In this case, you either first need to stop the container or use the -f
("force") option.
[~/docker_for_beginners]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e3eac2473614 alpine "/bin/sh" 19 hours ago Up 19 hours jolly_khayyam
[~/docker_for_beginners]$ docker rm jolly_khayyam
Error response from daemon: You cannot remove a running container e3eac247361447118efea112a078fa78bcf1b2e86db7acd87bc7357511286e75. Stop the container before attempting removal or force remove
[~/docker_for_beginners]$ docker rm -f e3eac2473614
e3eac2473614
[~/docker_for_beginners]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Note that removing a container does not remove the underlying image. To remove an image use docker rmi image-name
. If you attempt to remove an image and there are containers (running or not ) using that image you will get an error message
[~/docker_for_beginners]$ docker rmi centos
Error response from daemon: conflict: unable to remove repository reference "centos" (must force) - container ecc66757abbf is using its referenced image 67fa590cfc1c
If you really want to remove the image, you can then either remove all dependent containers first or force remove it with docker rmi -f image-name
.
We've seen how to: start a container in detached mode, keep a container alive, enter and exit a container, run a command in a running container, stop a container, remove a container.
how to: | command |
---|---|
start a container in the background | docker container run -d alpine ping host.docker.internal |
run a container in the background and keep it alive | docker container run -di alpine |
stop a running container | docker stop container_name_or_id |
execute the command uname -a in a running Docker container |
docker exec -it container_name_or_id uname -a |
start a shell inside a running container | docker exec -it container_name /bin/sh |
delete a container | docker container rm container_name_or_id |
force-delete a running container | docker container rm -f container_name_or_id |
remove an image | docker rmi centos |
force-remove an image | docker rmi -f centos |