Home > Enterprise >  How to make express visible outside docker container
How to make express visible outside docker container

Time:03-25

I am trying to setup docker with a nodejs/react env for local dev purposes, this is Dockerfile for client:

# Pull Docker Hub base image
FROM node:14.16.0-alpine3.10
# Set working directory
WORKDIR /usr/app
# Install app dependencies
COPY package*.json ./
RUN npm install -qy
# Copy app to container
COPY . .
# Run the "dev" script in package.json
CMD ["npm", "start"]

this is Dockerfile for server:

# Pull Docker Hub base image
FROM node:14.16.0-alpine3.10
# Set working directory
WORKDIR /usr/app
# Install app dependencies
COPY package*.json ./
RUN npm install -qyg [email protected]
RUN npm install -qy
# Copy app to container
COPY . .
# Run the "dev" script in package.json
CMD ["npm", "start"]

and this is docker-compose.yml:

version: "3"
services:

  client:
    build:
      context: ./client
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    networks:
      - picstack-network
    volumes:
      - ./client/src:/usr/app/src
      - ./client/public:/usr/app/public
    depends_on:
      - server
    environment:
      - REACT_APP_SERVER=http://localhost:5000
      - CHOKIDAR_USEPOLLING=true
    command: npm start
    stdin_open: true
    tty: true

  server:
    build:
      context: ./server
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    networks:
      - picstack-network
    volumes:
      - ./server/src:/usr/app/src
    depends_on:
      - db
    environment:
      - MONGO_URL=mongodb://db:27017
      - CLIENT=http://localhost:3000
    command: nodemon -L app.js

  db:
    image: mongo:3.6.19-xenial
    ports:
      - "27017:27017"
    networks:
      - picstack-network
    volumes:
      - mongo-data:/data/db

networks:
  picstack-network:
    driver: bridge

volumes:
  mongo-data:
    driver: local

and here's my entry point app.js:

var createError = require('http-errors');
var express = require('express');
const bodyParser = require("body-parser");
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

if I run docker-compose up, I can see the react index at http://localhost:3000, but I can't see the express index that is supposed to be at http://localhost:5000. docker ps shows all 3 containers are running and the log is free from errors.

however, if I stop docker and I run npm start locally, I can actually see the express index at http://localhost:5000.

So I suspect that when I run docker, http://localhost:5000 is only accessible from the client container, but I don't know how to verify it, and anyway I would like to be able to see the api from the outside when docker is running, so I can use Postman or similar. What should I change to achieve this?

I am really a newby with docker and express so any other suggestion to improve this configuration is welcome.

CodePudding user response:

As per discussion, you are not calling listen, in app.js. Therefore, your server will not start if you set the command in the compose file to command: nodemon -L app.js

I suggest to call app.listen in the app.js file.

app.listen(port, '0.0.0.0')

Then you can use nodemon again, as command.

nodemon -L app.js

By default nodemon monitors the current working directory.

  • Related