Introduction to Docker and Dockerizing Node.js applications
Introduction⌗
Docker is a platform for developing, shipping and running applications. Docker helps solve the issue of "It worked on my machine, don't know what happened here."
as it bundles up the application and its associated dependencies together as a container.
Why Docker ?⌗
In general, multiple computers running the same appliation are susceptible to errors related to dependency version differences, enviornment configuration issues etc.
By using Docker, we can easily avoid errors related to versioning, missing dependencies. Files similar to requirements.txt
, package.json
, gemfiles
are always coined together (Context of Web Apps). This ensures consistency on every build on every system.
The enviornment setup is easier using docker as it is lightweight, portable, testable on various operating systems. Also, Docker container runs on any machine that supports the container’s runtime environment.
Dockerfile⌗
A Dockerfile is a blueprint for buiding a docker image.
Note: This post is in context for Node.js applications.
- First, we must define from which image we would like to build using the
FROM
instruction.
FROM node:14
# Alternate
FROM node:version-alpine
- Define the working directory for your application (where the code resides) using
WORKDIR
instruction.
WORKDIR /app
- Now we need to install all dependencies from the
package.json
file. We need to copy thepackage.json
and the lockfile to ourWORKDIR
.
# A wildcard to include both package.json and package-lock.json
# Second argument indicates the workdir
COPY package\*.json .
RUN npm install
- Now we need to copy the source code using
COPY
instruction.COPY . .
copies all the files in the present directory (except the ones defined in.dockerignore
) to theWORKDIR
.
COPY . .
- Expose the
PORT
that your app uses.
EXPOSE 8000
- Define the command to run your app using
CMD
CMD ["node","app.js"]
Difference between CMD and RUN⌗
RUN⌗
This is an image build step. The state of the container after a RUN
command is committed to the container image. A dockerfile can have multiple RUN
steps that layer on top of one another in the build process.
Eg. RUN npm install
command would install all dependencies inside the container, this final state is committed to the container image.
CMD⌗
Lets you define a default command to run when your container starts. This is a run-time operation. Docker uses the final CMD
defined in the dockerfile to run.
.dockerignore file⌗
We need to create a .dockerignore
file in the same directory as your Dockerfile
to prevent your local modules, debug logs, lint files, etc. from being copied onto our Docker image.
Node.js Dockerfile⌗
# Specify Image
FROM node:alpine
# Create App Directory
WORKDIR /app
# Copy Dependencies
COPY package*.json ./
# Install App Dependencies
RUN npm install
# Copy App Source Code
COPY . .
# Expose port
EXPOSE 8080
# Start Application
CMD [ "npm", "start" ]
To build the docker file use,
docker build .
# With Tags
docker build . -t <your username>/node-app
To view created images,
docker images
# Example
REPOSITORY TAG ID CREATED
node alpine xxxxxxxxxxxx 5 days ago
<your username>/node-app latest xxxxxxxxxxxx 1 minute ago
To run the image use,
-p flag
redirects a public port to a private port inside the container.-d runs
the container in detached mode, leaving the container running as a daemon process.
docker run -p 5000:8000 -d <your username>/node-app
To see logs,
docker logs <container-id>
Cheers!
Pic Credits: Photo by Victoire Joncheray