What is Docker?
Docker is a platform for developing, shipping, and running applications in isolated environments called containers. It allows you to package an application with all its dependencies into a standardized software development and deployment unit.
Key benefits of Docker include:
Consistency across development, testing, and production environments
Easier application deployment and scaling
Improved resource utilization compared to traditional virtual machines
In this post, I will take you from the intro to ready-to-use docker. You will know everything you need to get started and work with docker. We will be understanding core concepts to creating and running your own containerized applications.
Core Concepts: Images and Containers
What is a Docker Image?
A Docker image is a lightweight, standalone, and executable package that includes everything needed to run a piece of software. This includes the code, runtime, system tools, libraries, and settings.
Think of an image as a blueprint or a snapshot of your application at a specific point in time. Images are the actual application artefacts that you can move around and share with others.
These images depend on other images, and they are stacked in that way. For example, a Node image might depend on Linux distribution such as a version of Alpine. When we pull another version of the same image we will see that the other image on which these images depend will not be pulled because they may have been pulled already for some other versions and support the current version we are pulling.
What is a Docker Container?
A container is a runtime instance of the image. Containers are the environments in which the images run.
When we say "docker run image-name", what's happening is:
Docker pulls the specified image (if it's not already available locally)
Docker creates a new container based on that image
Docker starts the container, which runs the application defined in the image
Each container has a unique container ID, which you can use to manage it.
Running Docker Images
Let's dive into how to run Docker images:
Pulling an Image
Before running an image, you need to pull it to your local machine:
docker pull image-name:tag
Replace image-name
with the name of the image you want to pull, and tag
with the specific version you need (if omitted, Docker will use the 'latest' tag). Docker will pull these images from a publicly hosted docker registry and for that, you will not need to log in. If you want to pull an image that is hosted in some private registry then you first need to log in and then run the above command.
Running an Image
To run an image and create a new container:
docker run image-name:tag
This command pulls the image (if not already present), creates a new container, and starts it.
Restarting a Stopped Container
If you have a stopped container that you want to restart:
docker start container-id
Replace container-id
with the ID of the stopped container.
Port Mapping
Often, you'll want access to the ports of the running container in docker. For that, you need to do the port mapping from the host (your local machine) to the container. To do that you will use the following command.
docker run -p host-port:container-port image-name:tag
For example, to map port 8080 on your host to port 80 in the container:
docker run -p 8080:80 nginx
Docker Compose
When your application consists of multiple services (like a web app, database, and cache), managing them individually can become cumbersome. This is where Docker Compose comes in handy.
Docker Compose allows you to define and run multi-container Docker applications. You use a YAML file to configure your application's services, networks, and volumes. Then, with a single command, you create and start all the services from your configuration.
Here's a simple example of a docker-compose.yml
file:
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
This file defines two services: a web server using the latest Nginx image, and a MySQL database.
To run your Docker Compose file:
docker-compose -f file-name.yml up
If your file is named docker-compose.yml
, you can simply run:
docker-compose up
To stop the running container you can do
docker-compose down
The above command will stop the running container and remove the image from your host as well.
This command builds, (re)creates, starts, and attaches to containers for a service.
Dockerfile: Building Your Images
While using pre-built images is convenient, you'll often need to create custom images for your applications. This is where Dockerfiles come in.
A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Here's a simple example:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
This Dockerfile:
Starts from the official Node.js 14 image
Sets the working directory in the container
Copies package.json and package-lock.json
Installs dependencies
Copies the rest of the application code
Exposes port 3000
Specifies the command to run when the container starts
To build an image from your Dockerfile:
docker build -t my-app:version .
This command builds an image named my-app
with the tag version
using the Dockerfile in the current directory (.
).
You can push your docker-compose file and Dockerfile to the version control host service you're using and anybody can easily run your application on their machine without any dependency on the machine they are using.
Conclusion
Docker provides a powerful set of tools for developing, shipping, and running applications. By understanding images, containers, Docker Compose, and Dockerfiles, you're well on your way to leveraging Docker in your development workflow.
Remember, practice makes perfect. Start small, perhaps by containerizing a simple application, and gradually work your way up to more complex setups. Happy Dockerizing!