Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deploy Angular 17 with SSR with Docker?

Tags:

docker

angular

Minimal Example

Setting up a new Angular 17 project (Node 18) as follows:

$ npm install -g @angular/cli@17
$ ng update @angular/core@17 @angular/cli@17
$ npm update

$ ng new example
stylesheets? $ SCSS
SSR? $ yes
$ cd example
$ ng serve

Connects just fine on localhost:4200.

Deploying it with Docker does not work, because all the example Dockerfiles expect older Angular versions without SSR.

Seriously, guys. Before giving an answer try actually creating an Angular 17 SSR project and try if it works with your Dockerfile.

Docker Failures

I tried following these suggestions (remember to replace as necessary e.g.the node version node:12-slim by node:18-slim, the project name sample-angular-app by the project name example, doing the ports correctly etc.):

  • https://dev.to/marwan01/deploy-an-angular-app-using-google-cloud-run-3p4a (there is no server.js)
  • https://dev.to/rodrigokamada/creating-and-running-an-angular-application-in-a-docker-container-40mk (builds but no connection possible - just gives the NGIX default page).
  • https://levioconsulting.com/insights/how-to-dockerize-an-angular-application-with-nginx/ (builds but no connection possible {connection reset} - and completely rebuilds the application on each docker run instead of only once).
  • https://blog.stackademic.com/deploy-your-angular-app-with-docker-and-nginx-a5b0a3c1d06b (the Dockerfile has a syntax error, and when built cannot connect {connection reset})
  • https://plainenglish.io/blog/how-to-dockerize-angular-application-3cd67e963832 (cannot connect {just gives the NGIX default page}, but at least it only builds once)
  • https://github.com/coltenkrauter/angular-ssr-example/blob/stable/Dockerfile.ssr (expects pre-Angular 17 SSR, needs to be rewritten, then no connection {refused to connect})
like image 551
user66554 Avatar asked Mar 09 '26 06:03

user66554


2 Answers

Dockerfile

FROM node:18-alpine as build
WORKDIR /app/src
COPY package*.json ./
RUN npm ci
COPY . ./
RUN npm run build

FROM node:18-alpine
WORKDIR /usr/app
COPY --from=build /app/src/dist/PROJECT_NAME ./
CMD node server/server.mjs
EXPOSE 4000

Docker invocation

docker build . -t PROJECT_NAME -f Dockerfile
docker run -d PROJECT_NAME -p 8080:4000

Notes

  • Replace PROJECT_NAME by the project name.
  • Need to use node:18 to support Angular 17.
  • Need to copy from dist/PROJECT_NAME/server to get the version that can be served.
  • Need to serve server.mjs, there is no server.js.
  • Need to make sure the ports are mapped correctly.
  • 4000 is the default port set in server.ts, see the line const port = process.env['PORT'] || 4000; in there. Of course one can define another port either by editing the server.ts or setting the PORT environment variable, but I kept it simple here.
  • 8080 is the port where one can see the project in the browser at http://localhost:8080/.
like image 190
user66554 Avatar answered Mar 10 '26 20:03

user66554


nginx

Starting from the accepted answer, I provide another solution which instead uses nginx to serve the application:

FROM node:18-alpine as build
WORKDIR /app/src
COPY package*.json ./
RUN npm ci
COPY . ./
RUN npm run build

FROM nginx:1.23
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
COPY --from=build /app/src/dist/$PROJECT_NAME/server /var/www/html
CMD ["nginx", "-g", "daemon off;"]

Now an example of nginx.conf (which has to be found on the same folder as Dockerfile) can be:

server {
    listen $YOUR_PORT;
    server_name localhost;

    # Serve static files
    location / {
        root /var/www/html;
        index index.html;

        try_files $uri $uri/ /index.html; 
    }
}

docker compose

Note that it's preferable to use docker compose to run docker containers, instead of the Dockerfile.

I also provide an example of docker-compose.yml (to be put in the same folder as Dockerfile).

version: '3.2'

services:
  ui:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "$YOUR_PORT:$YOUR_PORT"

now you can run:

docker compose build
docker compose up
like image 21
Francesco Urdih Avatar answered Mar 10 '26 19:03

Francesco Urdih