Search code examples
node.jsdockerdocker-composedevelopment-environmentproduction-environment

Node + Docker Compose: Development and production setup


I'm looking for a solution to have both a development and a production environment in my project using docker, docker-compose and nodejs.

How do I approach this?

Basically what I want is a command to start my docker production environment, and a command to start my development environment (which could use nodemon for example).

Here is my Dockerfile

FROM node:13-alpine

RUN mkdir /app

WORKDIR /app

COPY . /app

RUN npm install

RUN npm run build

EXPOSE 1234

CMD ["npm", "run", "prod"] # <--- Have a possibility to run something like "npm run dev" here instead

docker-compose.yml

version: "3"
services:
    findus:
        build: .
        ports:
            - "1234:1234"
        links:
            - mongo
        container_name: myapp
    mongo:
        image: mongo
        restart: always
        ports:
            - "4444:4444"

package.json

// ...
    "scripts": {
        "build": "tsc",
        "dev": "nodemon source/index.ts",
        "prod": "node build/index.js"
    },
// ...

Solution

  • You can make use of entrypoint and pass the command to the docker container. Then you can use docker-compose inharitance to launch compose for the environment that you want and append command to the entrypoint.

    Dockerfile :

    FROM node:13-alpine
    
    RUN mkdir /app
    
    WORKDIR /app
    
    COPY . /app
    
    RUN npm install
    
    RUN npm run build
    
    EXPOSE 1234
    
    ENTRYPOINT ["npm", "run"]
    

    Main docker-compose.yml :

    version: "3"
    services:
        findus:
            build: .
            ports:
                - "1234:1234"
            links:
                - mongo
            container_name: myapp
        mongo:
            image: mongo
            restart: always
            ports:
                - "4444:4444"
    

    And then have two docker-compose files to append the command passed to the image entry point. For development - docker-compose.dev.yml :

    version: "3"
    services:
        findus:
            command: dev
    

    and docker-compose.prod.yml :

    version: "3"
    services:
        findus:
            command: prod
    

    Then to launch dev environment :

    docker-compose  -f docker-compose.yml -f docker-compose.dev.yml up    
    

    and for prod environment :

    docker-compose  -f docker-compose.yml -f docker-compose.prod.yml up   
    

    So the command will be appended to the ENTRYPOINT instruction.


    Also this approach could work with enviroment variables if you wanted to pass the command as environment variable. You can find more information in the docs.