Common NodeJS + Docker Issues
This article is a list of the most common and notorious problems encountered when working with containerized NodeJS applications. It also aims to share a bunch of troubleshooting tips and tricks that you could use to diagnose and fix the issues.
DISCLAIMER: This article is not a complete absolute guideline on fixing problems with NodeJS applications inside containers. If you have ideas that you want to add and share to the community, message me up @ firstname.lastname@example.org and I would gladly accept and add it in the article.
Host Port is Taken
Everyone hates it when the port used by their application's container is taken. Docker will throw the dreaded error above which states that the container's port is taken. You will be haunted by this issue quite often and you have several options to fix it:
- Kill the process / container that took the port that the container needs.
- If you cannot kill the process / container that took the port, make way and use a different host port on your docker run command.
- On some machines, shutting down without stopping containers causes the port that they previously used don't get released. To fix the issue, you can restart your Docker daemon and it should fix the problem.
- Stop working until the app that took your port in a greedy fashion stops (Stop laughing! Maybe its an intermittent job!).
Internal (container) vs External (host) Ports are Swapped
Docker containers by default can make connections to the outside world, but the outside world cannot connect to containers. Docker allows you to enable incoming connections to the containers by supplying the -p hostport:containerport parameter.
There are days that you will get tired and you will accidentally swap the value of the host and container port (Host port is the port in the machine running the Docker Daemon where you want to expose your app and Container Port is the port inside the container). To avoid / reduce the occurrence of this problem, you can do any of the following:
- Unless you need a different host and container port, always try to use identical ports!
- Use docker compose files as they ease port management especially when working with several containers.
- Take a rest so you can stop inputting sh*tty port mappings.
Base Image does not contain an Installed NodeJS
So you were a Docker master for Java or C# and you tried copying Dockerfiles from those applications and placed them in your NodeJS project. Guess what? Most of the time, copying those Dockerfiles isn't going to work with baking NodeJS images.
- Use base images that have a pre-installed NodeJS installed.
- Make your own image and install NodeJS on your own.
- Give up using NodeJS and go back to Java and C#
Environment Variable Not Found
Environment variables are environment specific configurations that can be accessed through the use of NodeJS's process.env global object. On most applications, sensitive environment variables like (database connection string, message queue URLs, storage bucket keys, etc) won't be defined in a Dockerfile because doing so would pose a risk especially if you are using public Docker registries.
Running an image with an application that requires a sensitive environment variable would result to crash. To solve the problem you can take any of the following options:
- Use a configuration server and encrypt the sensitive environment specific variables (Thanks Nilesh!)
- Temporarily bake the sensitive environment variables on your Dockerfile and don't dare checking it in or pushing the image to your registry (I really don't suggest this idea but it will work as a dirty risky quick fix)
Application can't connect to local database
So your application runs perfectly on your development machine and you were able to successfully connect to your local database. However, after building your Docker image, you ended up seeing the connection failure issue above. This is mostly caused by the fact that the meaning of 127.0.0.1 and localhost are contextual to the execution point of your application.
In the case of applications running inside containers, using 127.0.0.1 and localhost in your connection strings are similar to informing your ORMs that the database resides inside the same container.
To solve the issue before your boss starts sending you photos of "It works on my machine" shirts, you can do the following:
- If you utilized localhost or 127.0.0.1, your container would think that the database is inside its sandbox, to solve the problem you can use your computer's IP address (Making it static is much more preferable as it won't break every time you get a new IP from the router's DHCP pool).
- Another option if you used localhost or 127.0.0.1 is to define an entry in your host file that would cause your machine to think that your db server is represented by a URL instead of an IP.
- Use an on-prem DNS server to create a local URL for your machine that host your database (If it is shared by developers)
- Stop connecting to databases :D (Offloading data persistence to background jobs is a thing for big platforms)
Container Starts and then Exits
A container's life cycle is coupled with the main process that executes on the container. When this process stops, the container would also stop. Below is a list of most probable reasons why your container would stop after running:
- Your docker file did not contained an ENTRYPOINT or CMD definition. The container's main process can be determined by the process that would usually be invoked in the ENTRYPOINT or CMD definitions.
- The main process in your container stopped because of the application's natural exit flow.
- Something (worst case somebody) killed the main process.
- The main process in your container crashed because of unhandled exceptions.
- Your container does not contain the app, therefore the invocation of the main process cannot occur.
In this article, we've learned the most common reasons why your NodeJS applications is not working and how to fix them inside containers.
PS: It really makes me sad when I am trying to diagnose issues and the problem originates on the containerization of the NodeJS app, so I decided to share this article to the world and I hope it will reduce stress and despair among developers.
- 10 Steps to Setup and Containerize an Express Server
- Azure Container Instances (ACI)
- Microservices: Why choose containers over virtual machines.
- Microservices: Picking the .NET Framework for your containerized applications.