Use the following files to dockerize a node application:
server.mjs
package.json
Dockerfile
.dockerignore
.env
# Instructions
Your goal is to have a docker container running that uses your most recent files on your host system as the application code that will be executed when you visit the web page running in the container. This way you can have a well-defined execution environment (using docker for managing the dependencies an environment), but still be able to make rapid changes to your code and test it out while developing.
- Build an image using the Dockerfile. Give it a tag of
bindmountimg
- Run a container based on the image using
docker run -it -p 8082:80 -v <absolute path to your working directory on the host machine>:/app -v /app/node_modules --rm --name bindmountcontainer bindmountimg
- Access the site in your browser
Under the URL: http://localhost:8082
- Make changes to your code and change the HTML output of your site.
- Refresh the page in the browser
Note: In Windows also type rs
in the console to refresh the container.
- You should see your updated view.
# Answering Questions
- How is the container port on which the application listens defined and managed?
The container listens on the port defined by the process.env.PORT
:
- What does the
ARG
command do in your Dockerfile, and how can you use that when building an image?
It defines a build-time-variable, that can only be used while the image-builds.
The value can be overwritten by the command docker build --build-arg DEFAULT_PORT=3000 -t myapp .
Example: We want to create a docker-image for an application.
- In development, it runs on port 3000
- In production, it runs on port 80
- Why does the application listen on the port defined in the environment variable?
The value process.env.PORT
is used to configure the server on app.listen(...)
- If we want to change the port, we don’t have to modify the code (only edit
.env
file)
- How can you set environment variables when running a container? (There are 2 ways. One might be connected to the .env file. But you should try it out to make sure.)
- .env file
- with docker run command
- What is a
.dockerignore
file?
Specifies files, that should be excluded from a docker image when it’s built (can be compared with a .gitignore
)
- Image sizes smaller
- Avoids copying unnecessary files
- What is
nodemon
and how did we use it in that example?
”Node” & “monitor”
nodemon is a utility, that automatically monitors changes in a Node.js app & automatically restarts the server when file-changes are detected.
- Note: On Windows you have to type
rs
to refresh the files - eliminates the need for manual restarts
In our case, we used nodemon
to run the server.mjs
file through the start script in package.json, enabling automatic restarts whenever code is modified.
package.json:
- Which part of the
docker run
command defines a bind mount?
In this case, the docker run ... -v ["host_path"]:[container_path] ...
defines the path on your host-computer, that you want to mount.
Then the directory on the host file system is shared with the container.
- Why did we have to specify an anonymous volume using
-v /app/node_modules
? What would happen if we left that out? (This last question is probably the most important question for you to understand how volumes and bind mounts interact with each other.)
Mounting the entire /app
folder from the host could overwrite the node_modules
in the container by the version of the host.
By using an anonymous volume for our node_modules
, docker keeps the dependencies isolated from other updates.
- Allows updating the app code & makes sure, that the dependencies remain stable