Logo Dave LobosDave Lobos About
Cover Image: Securely Running Third-Party Node.js Apps with Docker Compose

Securely Running Third-Party Node.js Apps with Docker Compose

Running third-party code on your machine always comes with a certain level of risk. This article will show you how to create a secure, isolated environment for any Node.js application using Docker Compose, complete with the added benefit of hot-reloading for a smoother development experience.

Why You Should Isolate Third-Party Applications

When you clone a repository from an untrusted source, you're not just getting the application's code; you're also getting all of its dependencies. These dependencies can contain malicious scripts that could potentially access your file system, steal your environment variables, or perform other unwanted actions.

By running the application inside a container, you create a sandboxed environment. This means the application's access to your local machine's filesystem and network is restricted, significantly reducing the potential damage from a malicious package. Think of it as a "cage" for the application, where it can only interact with what you explicitly allow.

GitHub Gist

Getting Started: The Setup

Let's assume you've just cloned a Node.js application into a directory named app:

git clone https://some-untrusted-repo.com/app

Now, in the root of your project (outside the app directory), create the following two files: docker-compose.yml and Dockerfile.

The Dockerfile

This file contains the instructions to build the Docker image for our application. It specifies the base image, sets up the working directory, copies the application code, and installs the dependencies.

# Use an official Node.js runtime as a parent image
FROM node:alpine

# Set the working directory in the container
WORKDIR /usr/src

# Copy the application code into the container
COPY app .

# Install application dependencies
RUN npm install

# Define the command to run your app
CMD ["npm", "run", "start"]

A quick breakdown:

The docker-compose.yml

This file is where we define and configure the services that make up our application. In this case, we have a single service for our Node.js app.

services:
  some-app:
    build: .
    ports:
      - "3000:3000"
      - "9229:9229"
    develop:
      watch:
        - action: sync+restart
          path: ./app
          target: /usr/src

Let's look at what's happening:

Running the Application

With your Dockerfile and docker-compose.yml in place, you can now start the application with a single command:

docker compose up --build --watch

Let's break down the flags:

Now, if you open your browser and navigate to http://localhost:3000, you should see the application running. Any changes you make to the code inside the app directory will trigger an automatic restart of the application within the container.

By following these steps, you've created a secure and efficient development environment for any third-party Node.js application. You've isolated it from your host machine, minimizing security risks, while also leveraging the power of Docker Compose's watch mode for a seamless hot-reloading experience. This approach allows you to explore and work with new codebases with greater confidence and productivity.