Docker Notes
Every useful information you need to know about Docker
What is Docker?
- Docker is the software used to build, run, and orchestrate containerized applications.
- When we talk about containerized applications, we’re not talking about apps running inside a virtual machine.
- A containerized application will run on its own context, using a minimum set of binaries.
- Thanks to Docker we have several apps running; each of them has a single context, which does not share it with any other app. At the same time, all the apps are running on top of the Docker Engine, which is the layer responsible for providing an interface from the apps to the OS and vice-versa.
- Any container itself is exportable, destroyable and immutable. That’s one of the most powerful features about Docker
What is a Docker Container?
- A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another
What is Docker Images?
- A Docker Image, in a logical way, is a container’s template.
- A Docker Image contains all the instructions and binaries necessary to build and run whatever containerized app you want.
- You can find docker images for any technology, language, or framework. All primary images are stored in a large repository called Docker Hub, which is the official image repository maintained by Docker.
Image commands
docker pull nginx
docker pull nginx:1.14.2
docker image ls
docker image
and click tab to see other commandsdocker image ls - a q
docker image rm img_nm_or_id
docker rmi img_nm_or_id
docker image rm $(docker image ls -a -q)
docker rmi $(docker images -a -q)
Container commands
docker container ls
docker container run --rm -p 80:80 --name myNginx nginx
docker container run
is the docker instruction to run containers , you can write --help after it to check more details.— rm
this flag indicates the container will be deleted once is stopped. Otherwise, we’re going to have to remove it manually.-p 80:80
indicates the ports to be published. The number before the colon is the port of your host machine. The number after the colon is the port used by the container. Thus, in this case, we are saying: direct the connections from port 80 from my machine to port 80 from the container, and vice-versa.— name myNginx
is giving our container the name “myNginx.” If we don’t indicate this, our container will default to a random name from the main Docker project contributors.nginx
is the name of the image, which is the only required parameter of the command.- we can yse othe args like
-e env_var=some_env_var
-d
to run in detached mode so the container will run on background
Containers Management
docker ps -a
docker container <action> <container_name>
docker container restart myNginx
docker container stop myNginx
docker contaimer start myNginx
docker container rm -f myNginx
docker container rm $(rm container ls -a -q)
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
Running commands inside a container
docker container exec -it myNginx bash
-it
makes possible to interact with the bash. The letter “i” is for making our shell interactive and “t” is for getting the output from that shell (TTY).myNginx
is the name of the running aimed container.bash
is the command name we want to use. In this case, since we want to get access to the shell, we need to use the command bash.
Once we run this command, we will see the Unix terminal of our nginx server. Here we can do anything. We can list directories, navigate through the filesystem, create new files or directories, check the processes running, etc. As an example, let’s create a new HTML file using this Unix command:
echo "<h1>Hello New File</h1>" >> /usr/share/nginx/html/new.html<br>
Now if we go to http://localhost/new.html, we will see the content of our new file. If we want to exit the bash, we can enter “exit,” and we’ll be out.
Keep in mind; not all images offer a “bash” option. They might have different ways to get access to the shell though. For example, in “alpine” images, you can access the shell with the command “sh” Take into account that you don’t need to get shell access to perform many actions.
Remember, you can always use “exec” with whichever command you want to use. Example:docker container exec myNginx ls
Storage in Docker
By using Storage in Docker we can persist data or files from the host system into our containers and vice-versa. To achieve this, we can either use Bind Mounts or Volumes.
- Bind Mounts: are used to storing files and directories into the container. Most of the time you will use them for your project files.
- Volumes: are used to persist data. You will use them for your Databases.
- So in short words: Use Bind Mounts for your project files and Volumes for your data.
Using bind mounts with an Nginx container
we want to bind the html folder on host machine to specific path on container
docker container run --rm -p 80:80 --name myNginx -v $(pwd)/html:/usr/share/nginx/html nginx
The main part is -v
argument and the two Unix paths separated by a colon $(pwd)/html:/usr/share/nginx/html
The first path is $(pwd)/html indicates the directory from the host machine that we want to mount; the second one is the destination directory path in the container.
In a few words, what we are doing here is asking docker to:
Take whatever is inside the path: <my_current_position>/html from my host machine and mount it on the following containers path: /usr/share/nginx/html.
From now and on, any change you make on your HTML files from your host machine will be automatically reflected on the HTML files from your container.
Using Volumes with a Mongo image
One of the characteristics of Docker containers is its “destroyable” nature, which means, we can delete any containers quickly without leaving any tracks behind, this is useful for many situations, but for some situatoins we need to persist data, the solution is “Volumes”
Volumes are specific units of storage managed by the Docker engine, which we can use to persist any required data. Most of the database images out there already have volumes configured by default. However, here we will learn to create our custom volumes and use them in our DB containers.
docker container run -d --name myMongo mongo
docker container inspect myMongo
docker volume ls
docker volume create my-mongo-volume
docker container run -d -v my-mongo-volume:/data/db --name myNewMongo mongo
we also use this time include a -v option, and we use the volume’s name that we created before my-mongo-volume. The part after the colon represents the destination path of the container — where the volume will be mounted. In this case, we want to mount a volume to persist our data, so we use the /data/db path.
Networks in Docker
So far, we have been dealing with a single container at the time. But we all know that’s not how real applications work. Nowadays, a minimum stack project consists of an API, a frontend app, and a Database entity — as to give the most simple example. We might also talk about a microservices architecture with many artifacts running simultaneously. How can we connect all these pieces using Docker?
If you want to connect two or more containers, so that they can communicate with each other, they have to share the same network. In Docker, there are multiple ways to achieve this, but not all of them are good.
In general, when it comes to choosing how our containers will be talking to each other, we have Good, Bad and Ugly ways:
- The Good: creating a specific bridge network. We are going to focus on this one.
- The Bad: publishing all the required ports and running the containers with the — net=”host” option. Please, don’t do this!
- The Ugly: Using the “link” option ( — link). It still works, but it’s planned to be removed soon.
For our example, we will connect a PHP-apache and a MySQL container using a bridge network.
Connecting two containers on the same network
Let’s start by first creating the network we want to use:
docker network create my-network
We can list the networks to verify the past command was successful using docker network ls
Now let’s start a PHP-apache
container and link it to our new network created. We use the --network
option for this:
docker container run -d --rm --network my-network --name php-server php:apache
Now it’s time for the MySQL
database:
docker container run -d --network my-network -e MYSQL_ROOT_PASSWORD=123456 --name mysql-db mysql
At this point, these two containers should be able to communicate with each other.
To confirm this, we can use the command ping
inside one of our containers.
Let’s get shell access into the PHP instance first:
docker container exec -it php-server bash
Unfortunately, this container doesn’t have available the ping command. So we need to install it:
apt-get update && apt-get install iputils-ping
After installing the ping tool inside the PHP container, we can proceed to ping the MySQL instance, using its container’s name. We should be able to see the ping responses.
ping -c 3 mysql-db
We will see, the container’s name will resolve to the container’s IP from your custom network. Which means the containers are connected.