50

I have this Docker Compose configuration where I simply create a NodeJS container and install Angular CLI inside.

After a docker-compose up -d, I'm able to SSH inside the container with docker-compose run node bash. ng new works perfectly but ng serve does not seem to work. It's launched correctly, no error in the console. But, if I visit localhost (ad I mapped port 4200 to 80), nothing loads.

Am I missing something?

zgue
  • 3,793
  • 9
  • 34
  • 39
Axiol
  • 5,664
  • 9
  • 37
  • 49

7 Answers7

60

In your Dockerfile you are missing the Expose line such as:

EXPOSE 4200

Try placing it before your last RUN command in the docker file.

This line exposes the port in the container itself (4200 in this case) so the mapping from compose works (80:4200).

Compose just does this: forward 80 from the host to 4200 in the container. But it doesn't know or care if the 4200 is actually being listened to. The Expose in the dockerfile makes sure when the image is built, to expose this port for the future running containers, so your ng serve can listen to it.


Resolution

So to get what you want with docker-compose run, use publish to publish the ports. As run doesn't use the mappings from your docker-compose.yml, it ignores them. So use it like this:

docker-compose run --publish 80:4200 node bash

Then create the angular app and start it up as you were doing.


Test Example For Future Reference

cd tmp (or any writable folder)

ng new myProject

cd myProject

ng serve --host 0.0.0.0 (--host 0.0.0.0 to listen to all the interfaces from the container)

Then in your browser, go to localhost and you should see the angular welcome page now as the port 4200 is published and bound to the host port 80 through the publish command as I showed above.

Everytime you have port forwarding issues, if you open a new terminal keeping the other terminal where you executed the original run command and run docker ps you will see this in the Ports column:

0.0.0.0:80->4200/tcp which means that your host on port 80 is forwarding to your container in port 4200 successfully.

If you see something like 4200/tcp and not the -> part, that means there is no mappings or ports published.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Juan
  • 6,125
  • 3
  • 30
  • 31
  • Oh, I did not know you had to manually expose ports, thanks. But still, it does not work. As you can see here, port is exposed https://github.com/Axiol/Docker-Angular-CLI/blob/master/.docker/node/Dockerfile But still does not load – Axiol Oct 17 '17 at 10:55
  • @Axiol I added an update to my response with all the steps to get what you want! – Juan Oct 21 '17 at 04:11
  • I am facing same issue , tried all above it doesnt help me .... (i) i am using EXPOSE correctly just above CMD["ng","serve","-H0.0.0.0"] , (ii) i see 0.0.0.0:80->4200/tcp .... when i go inside container & see process using ps -a i don't see npm running.... very new to npm & docker both , pls help – Lav Dec 28 '17 at 01:34
  • @Lav I'll be happy to help if you create a stackoverflow question with your specific case. – Juan Jan 03 '18 at 17:55
  • 2
    I'm using `docker-compose` and `angular-cli`, and had to use this `command` line for this to work: `command: "npm run -- ng serve --host 0.0.0.0 --disable-host-check"`. The `--host` part was being parsed by `npm run` rather than `ng serve` without the `--`. – mgarciaisaia Nov 08 '18 at 02:25
  • 2
    I think that ``EXPOSE 4200`` is just an indication for others developers using your Dockerfile, it does'nt really do anything https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#expose – vincent PHILIPPE Jul 28 '21 at 14:37
47

Using ng serve --host 0.0.0.0 has always worked for me.

The reason this is crucial is that without it, the angular process is only listening on the localhost interface inside the container - so even with the docker port mapping, connections from outside the container aren't being received.

** Angular Live Development Server is listening on localhost:3000

But if you add the parameter --host 0.0.0.0 then the angular process will listen on all interfaces, and the docker port mapping will allow connections from outside the container to reach it.

** Angular Live Development Server is listening on 0.0.0.0:3000

So, in summary:

  1. you don't need the EXPOSE 4200 line in the Dockerfile
  2. you do need the port mapping in the docker-compose.yml file
  3. you do need the CMD line in the Dockerfile, and it should include the host parameter e.g. CMD ["ng","serve","--host", "0.0.0.0"]
  4. you don't need to use docker run
  5. you can use docker-compose up, which will pick up the port mappings from the docker-compose.yml file.
Vince Bowdren
  • 8,326
  • 3
  • 31
  • 56
SamRR_75
  • 729
  • 8
  • 18
46

try to run ng serve with host specified (which is set to 'localhost' by default):

ng serve -H 0.0.0.0

UPDATE Pay attention, currently (@angular/cli@7) the option is --host:

ng serve --host 0.0.0.0 --disableHostCheck

thanks @antirealm for adding --disableHostCheck :)

Andriy
  • 14,781
  • 4
  • 46
  • 50
3

In my Dockerfile I was trying the --disable-host-check option but the browser would wait indefinitely:

CMD ["ng","serve","--host", "0.0.0.0", "--disable-host-check"]

So I added a hostname: dev.musicng property in my docker-compose.yml file, with its entry in the /etc/hosts file: 127.0.1.1 dev.musicng and then I could see my application appear in the browser.

Stephane
  • 11,836
  • 25
  • 112
  • 175
3

Project tree

enter image description here

.docker\node\Dockerfile

Install and configure Angular on node based container

FROM node:latest

RUN apt-get update && apt-get install -y vim

EXPOSE 4200

USER node

RUN mkdir /home/node/.npm-global
ENV PATH=/home/node/.npm-global/bin:$PATH
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global

RUN npm install -g @angular/cli@8.0.6

docker-compose.yml

  • Build the above Dockerfile

  • expose port 4200, run the command:

    ng serve --host 0.0.0.0 --poll=2000

--host 0.0.0.0 listen to all container interfaces
--poll=2000 listen for changes in the folder

version: "2.1"

services:
  node:
    container_name: angularcontainer
    build: ./.docker/node/
    ports:
      - 4200:4200
    volumes:
      - "./:/var/www/html"
    working_dir: /var/www/html
    command: ng serve --host 0.0.0.0 --poll=2000

Start

Run in project root

docker compose up

And done!

Project

https://github.com/wictorChaves/docker-helper/tree/master/projetos/compose/angular

Referencias:

Wictor Chaves
  • 957
  • 1
  • 13
  • 21
1
ng serve -H 0.0.0.0 

with 1000 poll property in angular-cli.json (for file change detection)

"defaults": {
    "styleExt": "scss",
    "component": {},
    "poll": 1000
  }
  • 1
    Your answer is a bit light on details. Could you explain what this is doing, and why it would solve the problem? – Adam Feb 22 '18 at 23:48
0

what you are doing is just installing the angular, you need to have CMD ["npm start"] or CMD ["ng serve"] at the end of dockerfile this is the entrypoint for the container which docker executes when you start the container and only then the npm server will start.

ng serve -H 0.0.0.0 --port <yourportnumber> will make the ngserve to run on localhost:<yourportnumber>there after you can bind the container port number to your local port

Vignajeth
  • 658
  • 1
  • 7
  • 10