How to deploy Angular 17 with SSR with Docker?
Asked Answered
R

5

9

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.):

Roots answered 20/1 at 7:30 Comment(0)
R
13

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/.
Roots answered 20/1 at 14:18 Comment(2)
You should include the browser folder too.Neoprene
thanks for your help :) just edit your answer to copy browser folder and start the right server fileStucker
H
4

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
Holtz answered 15/4 at 14:59 Comment(1)
Once I run docker compose up I get the following: $ docker compose up [+] Running 2/2 ✔ Network cataleya-ng_default Created 0.1s ✔ Container cataleya-ng-ui-1 Created 0.1s Attaching to ui-1 ui-1 | /bin/sh: 1: [nginx,: not found ui-1 exited with code 127Vevine
W
2
FROM node:20.10.0-alpine As builder
WORKDIR /usr/src/site.com/frontend
COPY ../package*.json /usr/src/site.com/frontend
RUN npm ci
COPY ../ .
RUN npm run build -c production
CMD ["node", "./docker/dist/frontend/server/server.mjs"]

It starts on default port - 4000. And u can use nginx.

Waylen answered 26/1 at 10:12 Comment(0)
P
0
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/YOUR_APP_NAME /usr/app/dist/YOUR_APP_NAME

CMD ["node", "dist/YOUR_APP_NAME/server/server.mjs"]

EXPOSE 4000
Prettify answered 9/8 at 12:52 Comment(0)
L
-1

Your app is written in TypeScript, but your Dockerfile is made for JavaScript apps. Have a look at TypeScript documentation on how to compile TypeScript to JavaScript. If you want a tutorial to follow, check out this one.

Lenitalenitive answered 20/1 at 7:59 Comment(3)
The TypeScript is compiled just fine. The point is that there exists no server.js, so the Dockerfile is wrong. So the question is how to get a correct Dockerfile.Roots
When you compile your project normally (not in a container), does server.js exist there?Lenitalenitive
Of course not. It's Angular 17, SSR, TypeScript. So you get dist/<project_name>/server/server.mjs.Roots

© 2022 - 2024 — McMap. All rights reserved.