Nine Docker pro tips for Node.js developers
Tags: containersecurity, docker, node
Published: 2024-04-12 02:00:32

If you spend quite a bit of time in the command line, working with Docker images and containers locally to build and test them, you might be in the mood for some power-user Docker commands.


We're skipping the basics and diving straight into the lesser-known yet highly effective commands that can significantly improve your Docker experience.


Are you concerned about the security of your Docker containers? Before we jump into the nitty-gritty of Docker commands, it’s crucial to acknowledge the importance of container security. This is where Snyk comes into play. Snyk offers robust security solutions tailored for containerized applications, helping you identify and fix vulnerabilities in your containers and their dependencies. [Start with integrating Snyk into your workflow](https://app.snyk.io/login/) for enhanced security.


How to get into the Docker container shell?
-------------------------------------------


It’s often necessary to debug issues on the container, such as inspecting logs, inspecting the file system structure, or meeting other requirements to validate or confirm a specific theory. Other times, you might wonder how you can explore the inside of a Docker image that you have built locally.


Here is how to open a shell for a Node.js Docker image with Docker’s *run* command:



```
$ docker run -it --rm [docker-image-name-goes-here] /bin/bash
```

You can do the above assuming that the `Dockerfile` for the Docker image did not specify an `ENTRYPOINT`.


How to find a Node.js Docker image version?
-------------------------------------------


Here is a cool trick for finding out which Node.js runtime version you have installed in your Docker image. This knowledge is vital for compatibility checks, debugging, and ensuring consistent behavior across different environments.


Run the following command (assuming you have the `jq` JSON parsing program installed):



```
$ docker image inspect [image-name] | jq '.[0].Config.Env'
```

The command outputs the environment variables of the Docker image, including the Node.js version. For example, you might see:



```
[
  "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  "NODE_VERSION=18.2.0",
  "YARN_VERSION=1.22.19"
]
```

How to use Apple M1-optimized Docker images?
--------------------------------------------


Docker has evolved to support the ARM architecture, which is the foundation of the M1 chip, offering specialized container images optimized for this architecture. These images ensure better compatibility and faster performance on M1 machines, which is helpful since many developers run on Apple laptops these days.


First, you might want to verify the image architecture. Before running a container, confirm its architecture compatibility. This command helps verify that you're using an M1-optimized image:



```
docker image inspect --format '{{ .Architecture }}' 
```

When you pull images from the Docker Hub registry, you’d want to make sure you are pulling M1-optimized images:



```
docker pull --platform linux/arm64/v8 node:lts-bullseye-slim
```

If you are also part of a team that builds Docker images and pushes them to a private or public registry, you’d also want to make sure you are building M1-specific container images so that they work seamlessly across different CPU architectures and help ensure broader compatibility:



```
docker buildx build --platform linux/amd64,linux/arm64 -t /: .
```

Spot changes to a container with Docker diff
--------------------------------------------


The `docker diff` command shows the changes made to a Docker container's file system since it was created. It reveals any files or directories that have been added, modified, or deleted. 


Here's how the command looks:



```
docker diff 
```

This command will return a list of changes made to the Docker container. For each change, Docker will indicate whether the file or directory was added (A), modified (C), or deleted (D).


The practical use of `docker diff` with a Node.js Docker container could be helpful if you’ve updated some dependencies in your `package.json` file and you want to verify what exactly has changed in the `node\_modules` directory. You can run the `docker diff` command to identify the changes.


### Benefits of `docker diff` in identifying security vulnerabilities


The `docker diff` command can be a powerful tool in your security toolkit too. It can provide a quick overview of any changes made to the Docker container's file system, which could potentially reveal unauthorized changes or suspicious activity. 


For instance, if you notice unexpected changes in your Node.js application files, it could be an indication of a security breach or vulnerability exploit. By integrating `docker diff` into your routine checks or even into your CI/CD process, you can improve the application security and ensure that your Docker containers are running as expected.


As such, you might want to utilize the command `docker diff` to perform a security audit of your Docker containers. By comparing the current state of the container to the original image, you can identify any deviations that may pose a security risk.


Scan your Docker container images for vulnerabilities and SBOM
--------------------------------------------------------------


Snyk is a security platform with an always-free tier designed to help developers with application security. When it comes to Docker, Snyk can scan your Docker images for vulnerabilities, providing you with a comprehensive report and actionable remediation advice.


To scan a Docker image of a Node.js project, first, ensure that you have the Snyk CLI (command line interface) installed. If it's not, you can install it using npm by running:



```
npm install -g snyk
```

Next, let's assume you have a Docker image of your Node.js application named `my-nodejs-app`. You can scan it with Snyk by using the following command:



```
snyk container test my-nodejs-app
```

This command tells Snyk to test the Docker image named `my-nodejs-app` for known vulnerabilities. After running the scan, Snyk will provide a list of vulnerabilities found in the Docker image, ranked by their severity level:



```
✗ High severity vulnerability found in lodash
  Description: Prototype Pollution
  Info: https://snyk.io/vuln/SNYK-JS-LODASH-567746
  Introduced through: lodash@4.17.15
  From: lodash@4.17.15
```

Another great feature of Snyk is its ability to produce a software bill of materials (SBOM) for your Docker image. An SBOM is a list of all components in your Docker image, including all dependencies and their versions. This is extremely useful for tracking what's inside your Docker image and for identifying potential vulnerabilities.


Here's how to produce an SBOM for your Docker image using Snyk:



```
snyk container test  --json | jq .packageManager
```

How to get the Docker image SHA ID?
-----------------------------------


It's crucial to use the Docker Image SHA ID to precisely reference your Docker images — especially in automated scripts or to ensure consistency across environments. This identifier is unique to each image and version, offering more specificity than tags.


This command lists all your Docker images with their full SHA256 digests. The SHA ID is displayed in the 'IMAGE ID' column:



```
docker images --no-trunc
```

### Usage scenario: Pinning an image in Docker Compose


When specifying an image in a Docker Compose file, you can use the SHA ID instead of the tag to pin the image to a specific version. This ensures that you always use the exact version of the image you tested your application with, avoiding unexpected changes if the image tag is updated.



```
services:
  your_service:
    image: your_image@sha256:
```

Using the SHA ID in Docker commands provides consistency and reliability, which is essential for production environments and CI/CD pipelines.


How to get the Docker container IP address?
-------------------------------------------


In scenarios where you're running Node.js applications with frameworks like NestJS, Express, or Fastify in Docker containers, it's often necessary to know the container's IP address.



```
docker inspect --format '{{ .NetworkSettings.IPAddress }}' [container_name_or_id]
```

How to inspect Node.js child processes inside a Docker container?
-----------------------------------------------------------------


How can Node.js developers can gain deeper insights into their containerized applications, allowing for more effective monitoring and troubleshooting, to debug whether the process uses more memory or CPU resources than expected?


Use this Docker command:



```
docker top node
```

When working with Node.js applications in Docker containers, especially those utilizing child processes (common in applications using clusters, workers, or spawning subprocesses for tasks), it's essential to have the ability to inspect these child processes for debugging and monitoring.


Query Node.js container image metadata at the Docker Registry API
-----------------------------------------------------------------


Sometimes you need detailed information about the Node.js container image, and directly querying the Docker Hub API is an effective method.


Use the following command, which relies on the `curl` program to make the HTTP request, and the `jq` program to format the response in a pretty-print JSON layout:



```
curl https://hub.docker.com/v2/repositories/library/node/tags/latest | jq
```

What you can expect in the response:


* **Image details:** Information like image size, digest, architecture, and more.
* **Layer information:** Understand how the image is constructed.
* **Tag details:** Specific data about the 'latest' tag.


Some use cases where this is helpful are automated scripts that integrate this command in CI/CD pipelines for automated checks/updates and version tracking to ensure you're using the correct version of the Node.js image for your project requirements.


You’ve reached the end!
-----------------------


We delved into various scenarios, from addressing version inconsistencies and performance bottlenecks to optimizing day-to-day operations within your Docker ecosystem.

In wrapping up, this post aimed to equip you with a suite of advanced Docker commands, transcending the standard fare of docker run and docker ps. These pro tips for DevOps and development professionals are intended to streamline your troubleshooting, debugging, and container management processes.


As you integrate these insights and commands into your workflow, remember that the journey of mastering Docker is ongoing. If you’re a Node.js developer, continue your learning with [these 10 best practices to containerize Node.js web applications with Docker](https://snyk.io/blog/10-best-practices-to-containerize-nodejs-web-applications-with-docker/), or if you’re a Java developer, you’ll enjoy Brian Vermeer’s [10 best practices to build Java containers with Docker](https://snyk.io/blog/best-practices-to-build-java-containers-with-docker/).