Search code examples
node.jsmacoslocalhostdockerboot2docker

Docker container with Node and Express on Mac, not showing in browser?


I'm delving into Docker and I'm trying to rack my brains on why this isn't working for me. I've read many articles and tutorials on how to setup this up and I seem to have everything in place, but my actual app just isn't showing up in the browser (localhost:3001). I'm using the latest version of Docker on my Mac, running Mavericks, using boot2docker. I definitely have boot2docker running as the docker commands run fine and I get no errors that seem to relate.

The super simple project looks like this:

src/
..index.js
..package.json
Dockerfile

The src/index.js file looks like this:

var express = require('express'),
    app = express();

app.get('/', function(req, res){
  res.send('Hello world!');
});

app.listen(3001);

The src/package.json file looks like this:

{
  "name": "node-docker-example",
  "version": "0.0.1",
  "description": "A NodeJS webserver to run inside a docker container",
  "main": "index.js",
  "dependencies": {
     "express": "*"
  }
}

The Dockerfile file looks like this:

FROM ubuntu:14.04

# make sure apt is up to date
RUN apt-get update

# install nodejs and npm
RUN apt-get install -y nodejs npm git git-core

# add source files
ADD /src /srv

# set the working directory to run commands from
WORKDIR /srv

# install the dependencies
RUN npm install

# expose the port so host can have access
EXPOSE 3001

# run this after the container has been instantiated
CMD ["nodejs", "index.js"]

With all of this in place, I then build it just locally:

$ docker build -t me/foo .

No problems... Then I've tried some alternative ways to make it run, but none of these work and I can't see any response when viewing in my browser (localhost:3001)

$ docker run -i -t me/foo
$ docker run -i -t -p 3001:3001 me/foo
$ docker run -i -t -p 127.0.0.1:3001:3001 me/foo

Nothing seems to work, no errors come up... Well, apart from that localhost:3001 in the browser does absolutely nothing.

Please help me! I love the idea of docker, but I can't get the simplest thing running. Thanks!


Solution

  • boot2docker has an extra network

    There's one extra layer of networking getting in the way. Remember that boot2docker has it's own OS and additional network IP, so try url=http://$(boot2docker ip):3001;curl -v "${url}" from a terminal on your mac and see if that returns HTML from your express app. If so, you can browse to your app with open "${url}".

    I was able to take your files (thank you for posting full files!) and build and run your image locally.

    Build, run, and test it like this

    docker build -t foo .
    docker run -i -t -p 3001:3001 foo
    

    I think the key thing to note is that for docker build the -t argument means "tag" but for docker run it means "allocate a tty".

    Test it like this (in a separate terminal from where it's running interactively)

    curl -s "$(boot2docker ip):3001"
    

    Here's where you went wrong

    Or at least my guesses:

    $ docker run -i -t me/foo

    doesn't map any ports

    $ docker run -i -t -p 3001:3001 me/foo

    I think in theory this variant should work. If not, I'm pretty sure it's a boot2docker-specific networking issue at the IP layer.

    $ docker run -i -t -p 127.0.0.1:3001:3001 me/foo

    This is telling docker to bind to loopback on the docker server, not your mac, so you'll never be able to connect to this from your mac.