ng serve not working in Docker container
Solution 1:
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.
Solution 2:
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
Solution 3:
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:
- you don't need the
EXPOSE 4200
line in the Dockerfile - you do need the port mapping in the docker-compose.yml file
- 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"]
- you don't need to use
docker run
- you can use
docker-compose up
, which will pick up the port mappings from the docker-compose.yml file.