Docker
Last updated
Last updated
This documentation has been made using the rooms Intro to Containerisation and Intro to Docker on TryHackMe
In computing terms, containerisation is the process of packaging an application and the necessary resources (such as libraries and packages) required into one package named a container. The process of packaging applications together makes applications considerably portable and hassle-free to run.
Image Source: TryHackMe
In the screenshot above, we can see how three applications and their environments (such as dependencies) are packaged together and do not directly interact with the physical computer - but rather the containerisation engine (in this case, it is Docker)
Docker employs the same technology used in containerisation to isolate applications into containers called the Docker Engine. The Docker Engine is essentially an API that runs on the host operating system, which communicates between the operating system and containers to access the system’s hardware (such as CPU, RAM, networking and disk)
Because of this, the Docker engine is extensive and allows you to do things like:
Connect containers together (for example, a container running a web application and another container running a database)
Export and import applications (images)
Transfer files between the operating system and container
Docker uses the programming syntax YAML to allow developers to instruct how a container should be built and what is run. This is a significant reason why Docker is so portable and easy to debug; share the instructions, and it will build and run the same on any device that supports the Docker Engine. The Docker engine allows containers to be orchestrated, meaning that multiple containers can be built as part of a group, allowing containers to communicate with each other (for example, one container running a web server and another container running a database can communicate).
The syntax for Docker can be categorised into four main groups:
Running a container
Managing & Inspecting containers
Managing Docker images
Docker daemon stats and information
docker pull imagename
Command to download the latest version of an image example: docker pull nginx
ubuntu
latest
docker pull ubuntu
- IS THE SAME AS - docker pull ubuntu:latest
This command will pull the latest version of the "ubuntu" image. If no tag is specified, Docker will assume you want the "latest" version if no tag is specified. It is worth remembering that you do not always want the "latest". This image is quite literally the "latest" in the sense it will have the most recent changes. This could either fix or break your container.
ubuntu
22.04
docker pull ubuntu:22.04
This command will pull version "22.04 (Jammy)" of the "ubuntu" image.
ubuntu
20.04
docker pull ubuntu:20.04
This command will pull version "20.04 (Focal)" of the "ubuntu" image.
ubuntu
18.04
docker pull ubuntu:18.04
This command will pull version "18.04 (Bionic)" of the "ubuntu" image.
docker image
list available options
docker image ls
list all images stored on the local machines
docker image rm imageId:tag
remove a docker image (we need to include the tag in the command example ubuntu:22.04
)
The Docker run command creates running containers from images. This is where commands from the Dockerfile (as well as our own input at runtime) are run.
docker run [OPTIONS] IMAGE_NAME [COMMAND] [ARGUMENTS...]
Command synopsis to tun an image
Example:
docker run -it helloworld /bin/bash
We run an image named helloworld.
"Interactively" by providing the -it switch in the [OPTIONS] command.
This will allow us to interact with the container directly.
We spawn a shell within the container by providing /bin/bash as the [COMMAND] part.
This argument is where you will place what commands you want to run within the container (such as a file, application or shell!)
-d
This argument tells the container to start in "detached" mode. This means that the container will run in the background.
N/A
docker run -d helloworld
-it
This argument has two parts. The "i" means run interactively, and "t" tells Docker to run a shell within the container. We would use this option if we wish to interact with the container directly once it runs.
N/A
docker run -it helloworld
-v
This argument is short for "Volume" and tells Docker to mount a directory or file from the host operating system to a location within the container. The location these files get stored is defined in the Dockerfile
VOLUME
docker run -v /host/os/directory:/container/directory helloworld
-p
This argument tells Docker to bind a port on the host operating system to a port that is being exposed in the container. You would use this instruction if you are running an application or service (such as a web server) in the container and wish to access the application/service by navigating to the IP address.
EXPOSE
docker run -p 80:80 webserver
--rm
This argument tells Docker to remove the container once the container finishes running whatever it has been instructed to do.
N/A
docker run --rm helloworld
--name
This argument lets us give a friendly, memorable name to the container. When a container is run without this option, the name is two random words. We can use this open to name a container after the application the container is running.
N/A
docker run --name helloworld
Other arguments include (but are not limited to!):
Telling Docker what network adapter the container should use
What capabilities the container should have access to.
Storing a value into an environment variable
docker ps
list running containers
docker ps -a
list all containers (even stopped)
Dockerfiles is a formatted text file which essentially serves as an instruction manual for what containers should do and ultimately assembles a Docker image.
INSTRUCTION argument
Dockerfile formatting
FROM
This instruction sets a build stage for the container as well as setting the base image (operating system). All Dockerfiles must start with this.
FROM ubuntu
RUN
This instruction will execute commands in the container within a new layer.
RUN whoami
COPY
This instruction copies files from the local system to the working directory in the container (the syntax is similar to the cp
command).
COPY /home/cmnatic/myfolder/app/
WORKDIR
This instruction sets the working directory of the container. (similar to using cd
on Linux).
WORKDIR / (sets to the root of the filesystem in the container)
CMD
This instruction determines what command is run when the container starts (you would use this to start a service or application).
CMD /bin/sh -c script.sh
EXPOSE
This instruction is used to tell the person who runs the container what port they should publish when running the container.
EXPOSE 80 (tells the person running the container to publish to port 80 i.e. docker run -p 80:80)
docker build
will be used to build an image with a Dockerfile.
To build it we would run docker build -t helloworld .
(the .
is to mention that the dockerfile is in our current working directory)
docker build -t webserver .
to build it
docker run -d --name webserver -p 80:80 webserver
to run it
Docker Compose allows multiple containers (or applications) to interact with each other when needed while running in isolation from one another.
Source: TryHackMe
Install Docker Compose
up
This command will (re)create/build and start the containers specified in the compose file.
docker-compose up
start
This command will start (but requires the containers already being built) the containers specified in the compose file.
docker-compose start
down
This command will stop and delete the containers specified in the compose file.
docker-compose down
stop
This command will stop (not delete) the containers specified in the compose file.
docker-compose stop
build
This command will build (but will not start) the containers specified in the compose file.
docker-compose build
An E-commerce website running on Apache
This E-commerce website stores customer information in a MySQL database
We could manually run the two containers via the following:
Creating the network between the two containers: docker network create ecommerce
Running the Apache2 webserver container: docker run -p 80:80 --name webserver --net ecommerce webserver
Running the MySQL Database server: docker run --name database --net ecommerce webserver
We can use Docker Compose via docker-compose
up to run these containers together.
Advantages:
One simple command to run them both
These two containers are networked together, so we don’t need to go about configuring the network.
Extremely portable. We can share our docker-compose.yml file with someone else, and they can get the setup working precisely the same without understanding how the containers work individually.
Easy to maintain and change. We don’t have to worry about specific containers using (perhaps outdated) images.
Necessary instruction of this use case
version
This is placed at the top of the file and is used to identify what version of Compose the docker-compose.yml is written for.
'3.3'
services
This instruction marks the beginning of the containers to be managed.
services:
name (replace value)
This instruction is where you define the container and its configuration. "name" needs to be replaced with the actual name of the container you want to define, i.e. "webserver" or "database".
webserver
build
This instruction defines the directory containing the Dockerfile for this container/service. (you will need to use this or an image).
./webserver
ports
This instruction publishes ports to the exposed ports (this depends on the image/Dockerfile).
'80:80'
volumes
This instruction lists the directories that should be mounted into the container from the host operating system.
'./home/cmnatic/webserver/:/var/www/html'
environment
This instruction is used to pass environment variables (not secure), i.e. passwords, usernames, timezone configurations, etc.
MYSQL_ROOT_PASSWORD=helloworld
image
This instruction defines what image the container should be built with (you will need to use this or build).
mysql:latest
networks
This instruction defines what networks the containers will be a part of. Containers can be part of multiple networks (i.e. a web server can only contact one database, but the database can contact multiple web servers).
ecommerce
Final docker-compose.yml file
When you install Docker, there are two programs that get installed:
The Docker Client
The Docker Server
Docker works in a client/server model. Specifically, these two programs communicate with each other to form the Docker. Docker achieves this communication using something called a socket. Sockets are an essential feature of the operating system that allows data to be communicated. In the context of Docker, the Docker Server is effectively just an API. The Docker Server uses this API to listen for requests, whereas the Docker Client uses the API to send requests. because of this, we can interact with the Docker Server using commands like curl or an API developer tool such as Postman.
Docker Registries, are used to store and provide published Docker images for use. Using repositories, creators of Docker images can switch between multiple versions of their applications and share them with other people with ease. Public registries such as DockerHub exist, however, many organisations using Docker will host their own "private" registry.
network ls
Used to list the networks of containers, we could use this to discover other applications running and pivot to them from our machine!
images
List images used by containers, data can also be exfiltrated by reverse-engineering the image.
exec
Execute a command on a container
run
Run a container