TIL — Docker
Reference
April 12, 2020
Today in class I got an overview of Docker. Here are the slides from class (note: they are a few years old and some links are outdated.). Here is the Docker documentation.
The Basics of Docker-izing An App
- Add a
Dockerfile
file to your project root - Add a
.dockerignore
file to ignore things likenode_modules
docker build
creates an image of the applicationdocker run
creates a container from your app image and spins it up- You can stop a single container normally with Ctrl + C
- Alternatively,
docker-compose up
create multiple containers if you have adocker-compose.yml
file docker-compose down
will stop all running containers gracefully
Dockerfile
The Dockerfile
is instructions for how to set up the container (see docs):
- Start with an image that you’re building
FROM
(like Node, PHP), etc. - You can
COPY
orADD
application code into the container WORKDIR
is the working directory where the application code will run from and be copied to./usr/src/app
is a common convention apparently but it can be anything…best to avoid the root though.RUN
any commands that need to go before your app will run (for examplenpm install
)CMD
must be the last command which tells the container how to start the app (i.e.npm start
). Only the lastCMD
instruction will be carried out.
Here are some examples to run simple apps:
# Java Application |
docker build
The command order is:
docker build -t <app-name>:<version tag (optional, default: 'latest' )> <src dir path> |
For example if I have navigation to my myApp
application folder in the command line, I can run docker build -t myApp:0.0.1 .
-t
will make the build logs show in your terminal- You can make up your app name and version tag
- Don’t forget the
.
at the end which is in reference to the present directory, where your app andDockerfile
are sitting
If it has built correctly, you’ll see the myApp
image on the list when you run docker images
.
docker run
Example: docker run -it -p 3333:3333 node-mongo:0.0.1
-it
gives you an interactive terminal for your app-p 3333:3333
is port mapping, in case you need to avoid port conflicts on your local machine without changing the application code. It publishes to your localhost from the app:-p 127.0.0.1:4000:3333
where the app runs on port3333
.- In this example
node-mongo:0.0.1
is the app name and version tag, as seen in thedocker images
list.
You can run a container in detached mode (i.e. in the background) with docker run -d
and you won’t have access to its interactive terminal. See docs.
You can also run docker exec -ti <CONTAINER_ID> bash
to inspect with the command line. exit
to leave.
Docker Compose
A docker-compose.yml
file gives instructions when you need to spin up more than one container to run your app, for example if you need your app server and database server running simultaneously. Here is the docker-compose v3 documentation.
Very important! If you docker-compose down
a server that contains data (like a database server) then all the data will be trashed. The solution is to use VOLUMES to write the data to disk (see docs). Here’s an example of an app which requires a MongoDB server:
version: "3" |
More Docker Commands
docker images
shows you what images you havedocker image rm <image-name>:<version-tag>
deletes the image from your Docker daemondocker ps -a
shows what containers are running
Best Practices
Be careful when writing the Dockerfile
and be as specific and detailed as possible to ensure the app runs consistently over time.
Be specific when pulling an image to create a container. For example docker pull node:12.16
is better than docker pull node:lts
because over time, the lts
version will change, and your docker container will be updated on its own. Read: things might break! This article explains this in depth.
Didn’t learn this, but multi-stage builds are a way to get smaller containers. For example you can build from a slim version of a language or runtime and then pull in dependencies as they are needed. This article explains this in depth; see also Docker docs on the topic.
The Best Bit
Since I don’t really develop with others, I don’t have much use case yet for Docker-izing my apps. BUT using Docker will allow me to learn new things which might require different languages more easily, because I won’t need to go through a massive local installation every time. I can just create a container with the image of whatever language and off we go!