3

I'm trying to use Docker to containerize an app built using the Angular CLI. It's just the default files that come when you use ng new so that I can learn how to do this. I'm trying to use a two-step build, where the first step runs ng-build --prod --build-optimizer, and then the result of that in the ./dist folder is put into a container with Nginx that serves the app. I know that if I manually build the app from my command line, then run a Dockerfile with only the second step that I can get the Angular app to be served, but I'd like Docker to do that for me.

Here's my Dockerfile:

FROM node:8.9-alpine as angular-built
COPY package.json package.json
RUN npm install
COPY . .
RUN ng build --prod --build-optimizer

FROM nginx:alpine
LABEL author="Preston Lamb"
COPY --from=angular-built ./dist /usr/share/nginx/html
EXPOSE 80 443
ENTRYPOINT [ "nginx", "-g", "daemon off;" ]

I've tried using the node:8.9-alpine base image as well as the johnpapa/angular-cli base image on the first step of the Dockerfile. Everything works until the RUN ng build --prod --build-optimizer command, at which point it fails with this error:

Cannot read property 'config' of null TypeError: Cannot read property 'config' of null at Class.run (/node_modules/@angular/cli/tasks/build.js:15:56) at Class.run (/node_modules/@angular/cli/commands/build.js:216:26) at resolve (/node_modules/@angular/cli/ember-cli/lib/models/command.js:261:20) at new Promise () at Class.validateAndRun (/node_modules/@angular/cli/ember-cli/lib/models/command.js:240:12) at Promise.resolve.then.then (/node_modules/@angular/cli/ember-cli/lib/cli/cli.js:140:24) at

After googling that, I found that it's because the CLI can't find the .angular-cli.json file. Then I read that by default, Linux doesn't copy hidden files, so it doesn't copy the .angular-cli.json file, and that's where the error comes up.

My next step was trying to force that file to be copied. I tried both of the following, putting this step right before the COPY . . command:

COPY .angular-cli.json .angular-cli.json

and

RUN shopt -s dotglob

The first one doesn't seem to do anything; I got the same error as before. The second one produces a different error:

/bin/sh: shopt: not found

So the command I found to run to tell Linux to copy the hidden files as well doesn't work. I saw one question that was different than this but related say to change the shopt call a little to the following:

RUN /bin/sh -c "shopt -s dotglob"

But that didn't do anything. I got the same not found error.

So I'm not sure where to go from here. any help would be greatly appreciated.

2
  • Maybe the example Dockerfile in the README of this project on GitHub solves your problem Commented Dec 6, 2017 at 8:03
  • Try running ng init before the build step. Commented Dec 6, 2017 at 8:06

1 Answer 1

15

If you use a node alpine image to build your angular app, you need to install the angular cli. Notice the npm i -g @angular/cli in the Dockerfile below. I also added a working directory to the first build stage.

Then you can run the docker compose commands (or docker build and docker run) for an out of the box angular cli app to run on nginx

Dockerfile

FROM node:8.9-alpine as angular-built
WORKDIR /usr/src/app
RUN npm i -g @angular/cli
COPY package.json package.json
RUN npm install --silent
COPY . .
RUN ng build --prod

FROM nginx:alpine
LABEL author="John Papa"
COPY --from=angular-built /usr/src/app/dist /usr/share/nginx/html
EXPOSE 80 443
CMD [ "nginx", "-g", "daemon off;" ]

docker-compose.debug.yml

version: '2.1'

services:
  clean:
    image: clean
    build: .
    environment:
      NODE_ENV: development
    ports:
      - 80:80
      - 443:443
      - 9229:9229
    ## set your startup file here
    command: [nginx-debug, '-g', 'daemon off;']

If you want to use an image based on alpine node 8.9 with the angular cli 1.5.5 already baked in, use this:

Dockerfile

FROM johnpapa/angular-cli as angular-built
WORKDIR /usr/src/app
COPY package.json package.json
RUN npm install --silent
COPY . .
RUN ng build --prod

FROM nginx:alpine
LABEL author="John Papa"
COPY --from=angular-built /usr/src/app/dist /usr/share/nginx/html
EXPOSE 80 443
CMD [ "nginx", "-g", "daemon off;" ]

BTW - the 1.5 version of the CLI has the --build-optimizer baked in, so it is not needed there

Sign up to request clarification or add additional context in comments.

3 Comments

I created a repo that runs the CLI out of the box that you can try. github.com/johnpapa/angular-cli-docker-ootb
Thanks! That worked perfectly. I used the second Dockerfile example and it worked. I had done everything except setting the WORKDIR, so next time I'll remember that as well. Thanks for your help!
@JohnPapa i followed the same steps but when i run docker-compose up the nginx gets started but exits when i break the shell. When i move to production i will have to run it in backgroun right? Any idea why. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.