Learning Docker
I’m re-learning Docker after 7/8 years or so of not using it 😬. These are some of my rough notes.
What Is It?
- Package software to run on any hardware
- Runs your code & the required environment in a container
- Environments are easily and consistently reproduced
Installing
Docker
I’m using Docker Desktop for Mac. Installing this installs all the needed CLI tools, as well as a UI for seeing processes, inspecting them, and shutting them down.
Tools
Docker VSCode extension from MSFT
Basic Terminology
Dockerfile
This is the instructions, or blueprint for creating an Image
Image
This is the actual artifact that can be moved/shared/published to a repo.
It contains the linux distro, applications, source code, etc.
An image is the output generated from the Dockerfile.
Container
This is a running environment for an image.
Core Commands
docker ps
- show running processesdocker ps -a
- show all processes, included those that have exiteddocker images
- show a list of imagesdocker run
- create a new container from an imagedocker stop
- stop a running containerdocker start
- start an existing container
Dockerfile
Create the Dockerfile
in the root of your project.
# source image to build from
FROM node:16-alpine
# working directory in the container
WORKDIR /usr/server/app
# copy files from host to container
COPY ./package.json ./
# run npm install to install dependencies in the container
RUN npm install
# copy files from host to container
COPY ./ .
# build the app in the container
RUN npm run build
# set the NODE_ENV to production
ENV NODE_ENV=production
# start the app in the container
CMD ["npm", "start"]
- Start from a base image with
FROM
and the image name & tag WORKDIR
is like runningcd
in your terminal. It sets the working directory to run subsequent commands inCOPY
will copy files from host (the machine this is running from) to the imageRUN
will run commands, so we copy thepackage.json
, then install dependencies- NOTE: Docker commits each step as a layer, this is why we copy the
package.json
file and install deps before copying the rest of the source code. If our source changes, but the deps don’t, spinning up the container will be faster since it will rely on cached layers forpackage.json
and the resulting deps.
- NOTE: Docker commits each step as a layer, this is why we copy the
ENV
sets environment variablesEXPOSE
will expose specific ports TODO: add example aboveCMD
will run a command. This is different fromRUN
because this is an entry point command. You only have one of these, but you can have multipleRUN
steps. This is the thing that starts your server/database/whatever
.dockerignore
You should also add a .dockerignore
file to the project root. This works just like a .gitignore
file and excludes certain files from COPY
operations in the Dockerfile
.
Building the Image
NOTE: You’ll want to make sure the
docker build -t <username/tag>:<version> .
-t
allows you to tag the image. The tag can have slashes, often used to applyregistryDomain/<ACTUAL TAG>
with an optional version added on with a colon.- registryDomain/tag will come into play when pushing to your account on Dockerhub
.
This is the path, in this case, just the current working directory on the host machine.
Running a Container
docker run -p 5000:8080 -d <imagename-or-id>
-p
is port forwarding in the formatlocal:container
so the host machine’s port5000
would forward to8080
in the container.-d
will run the container in “detached” mode.
Pushing the Image to a Repo
Not a git repo, but something like Dockerhub or AWS ECR (Elastic Container Registry)
TODO: docker push information
Pulling an Image from a Repo
TODO: docker pull information
Docker Compose
Using compose allows you to