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
Dockerfilefile to your project root - Add a
.dockerignorefile to ignore things likenode_modules docker buildcreates an image of the applicationdocker runcreates a container from your app image and spins it up- You can stop a single container normally with Ctrl + C
- Alternatively,
docker-compose upcreate multiple containers if you have adocker-compose.ymlfile docker-compose downwill 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
COPYorADDapplication code into the container WORKDIRis the working directory where the application code will run from and be copied to./usr/src/appis a common convention apparently but it can be anything…best to avoid the root though.RUNany commands that need to go before your app will run (for examplenpm install)CMDmust be the last command which tells the container how to start the app (i.e.npm start). Only the lastCMDinstruction 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 .
-twill 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 andDockerfileare 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
-itgives you an interactive terminal for your app-p 3333:3333is 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:3333where the app runs on port3333.- In this example
node-mongo:0.0.1is the app name and version tag, as seen in thedocker imageslist.
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 imagesshows you what images you havedocker image rm <image-name>:<version-tag>deletes the image from your Docker daemondocker ps -ashows 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!