the problem is that code is not being compiled realtime like if I would "ng serve" regularly w/o docker.
This is exactly expected in you current workflow as you are copying files into Docker image once during docker build, exactly one line COPY . /ng17/
I suggest you to build simple image by using
FROM node:20.11.0-alpine
WORKDIR /work
RUN npm install -g @angular/cli
CMD npm install && ng serve --host 0.0.0.0
You need only angular CLI installed during build, rest will be provided during starting container as you want real-time update
Of course to build it use the same command that you have already: docker build -t ng17:0.1 .
To start a container use a little bit longer command
docker run --init --rm -t --net host -v $PWD:/work:rw -u $(id -u):$(id -g) ng17:0.1
- Instead of using port mapping (
-p 4201:4200), I think(for development) simpler is using --net host but it's about preferences both will work.
--rm is just to remove container when it exits as it's not needed, all our changes are mount using -v, so we don't care about other changes inside container and it keeps docker containers cleaner (if you type docker ps -a without cleaning old containers list might be long and just eat your disk space)
- Angular
ng serve as I tested doesn't work well with Ctrl+C to stop it, quick fix for it is use --init (it can used with any application that is not correctly handling signals)
-t this added tty to running container, so when npm install packages you will see progress, without this you might think nothing going on as progress bar will not appear
- I removed
-d as like to have open console open somewhere and see logs, without this when your angular app fails to compile you have to use docker log $CONTAINER_NAME to see what went wrong, it makes life harder. Also when you are done with work just pres Ctrl+C in that console and container exits and everything is cleaned up
- Next
-v $PWD:/work:rw it will mount your current working directory into running container and this what makes changes in your IDE instantly visible by the container to ng serve can reload app. I also added :rw as all changes made by the container are visible on the host, mostly because when npm install install packages that we want to persist between container restarts
- Last parameter is
-u $(id -u):$(id -g), by default most Docker images run as root but when you local user(on host machine) is in 99% cases different so, it will end up that some files are owned by your local user and rest(mostly node_modules) by the root and this makes it harder to deleted when you have to, so force same user in the container as is used in the host machine
All this docker run can be changed to docker-compose, so you will be able to setup everything by shorter command: docker-compose up
version: '3.9'
services:
frontend:
build: .
init: true
tty: true
user: "${UID:-1000}:${GID:-1000}"
network_mode: host
volumes:
- $PWD:/work:rw
Unfortunately this version has harder to makes correct user id inside the container, so I default it to 1000 that is in many cases correct, you can manually change it to correct value or start docker-compose using
UID=$(id -u) GID=$(id -g) docker-compose up
Note: If you have latest docker version you can use docker compose instead of docker-compose command (space instead of dash(-))