2

I am trying to Dockerize and deploy an Angular app. I have the following:

Dockerfile

FROM node
WORKDIR /usr/src/app
COPY package.json package.json
RUN npm install --silent
COPY . .
RUN node_modules/.bin/ng build --prod
FROM nginx:alpine
WORKDIR /usr/src/app
RUN rm -rf /usr/share/nginx/html/*
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY /dist/nexct-approval-ui /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]

Then I run:

docker stop /ng-nexct-approval-ui-container
docker build --pull --rm -f "Dockerfile" -t ng-nexct-approval-ui-image:latest "."

I get he following output:

/ng-nexct-approval-ui-container
Sending build context to Docker daemon  541.9MB
Step 1/12 : FROM node
latest: Pulling from library/node
Digest: sha256:a6be25f2f9b8af240ee0b50aeee089bc66c23dfe95053a4de289b8d9efebdc44
Status: Image is up to date for node:latest
 ---> 37ad18cd8bd1
Step 2/12 : WORKDIR /usr/src/app
 ---> Using cache
 ---> a497790a47a4
Step 3/12 : COPY package.json package.json
 ---> Using cache
 ---> 784e7d4b48f6
Step 4/12 : RUN npm install --silent
 ---> Using cache
 ---> 63fd9d88955f
Step 5/12 : COPY . .
 ---> 9028e45e0701
Step 6/12 : RUN node_modules/.bin/ng build --prod
 ---> Running in dca7a1305fa9
Generating ES5 bundles for differential loading...
ES5 bundle generation complete.

chunk {2} polyfills-es2015.d26681d378262fd3296d.js (polyfills) 36.1 kB [initial] [rendered]
chunk {3} polyfills-es5.ca016a6f12d7e632666f.js (polyfills-es5) 129 kB [initial] [rendered]
chunk {0} runtime-es2015.0dae8cbc97194c7caed4.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.0dae8cbc97194c7caed4.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.d2d6ea2818487d59afe5.js (main) 1.86 MB [initial] [rendered]
chunk {1} main-es5.d2d6ea2818487d59afe5.js (main) 1.98 MB [initial] [rendered]
chunk {4} styles.f52187462d1cfca0d78e.css (styles) 62.1 kB [initial] [rendered]
Date: 2020-07-22T10:14:36.958Z - Hash: d17c8f049f83f75a6b04 - Time: 69588ms

WARNING in budgets: Exceeded maximum budget for initial-es5. Budget 2 MB was not met by 168 kB with a total of 2.16 MB.
Removing intermediate container dca7a1305fa9
 ---> f395c253b4ed
Step 7/12 : FROM nginx:alpine
alpine: Pulling from library/nginx
Digest: sha256:ee8c35a6944eb3cc415cd4cbeddef13927895d4ffa50b976886e3abe48b3f35a
Status: Image is up to date for nginx:alpine
 ---> ecd67fe340f9
Step 8/12 : WORKDIR /usr/src/app
 ---> Running in e9a249ce0b36
Removing intermediate container e9a249ce0b36
 ---> 453af4305629
Step 9/12 : RUN rm -rf /usr/share/nginx/html/*
 ---> Running in ba40b25e4973
Removing intermediate container ba40b25e4973
 ---> f813f1d121b1
Step 10/12 : COPY nginx.conf /etc/nginx/conf.d/default.conf
 ---> a6c544d4efdd
Step 11/12 : COPY /dist/nexct-approval-ui /usr/share/nginx/html
COPY failed: stat /var/lib/docker/tmp/docker-builder401838835/dist/nexct-approval-ui: no such file or directory

Question

How do I fix the no such file or directory error?

I think this is related to the WORKDIR /usr/src/app.

Thanks

5
  • Where does the /dist/nexct-approval-ui directory comes from ? Is it generated on your first stage or do you have it locally ? Commented Jul 22, 2020 at 10:23
  • If i rung ng build locally it generates it. However, I am now trying to generate the dist folder by running ng build in the Dockerfile. So maybe I am doing that incorrectly. Commented Jul 22, 2020 at 10:25
  • 1
    You must reference your first stage when you do the COPY otherwise docker will look on your local folder only. Use COPY --from=0. For reference docs.docker.com/develop/develop-images/multistage-build/… Commented Jul 22, 2020 at 10:28
  • 1
    You execute the build command in the first container after setting the working directory to WORKDIR /usr/src/app. Unless you have instructed your build script to do otherwise, you should find the /dist/ in the working directory. Commented Jul 22, 2020 at 10:50
  • 1
    Alternatively you can add the --output-path option to your ng build command and specify any path you'd like, as @user3362334 suggested. Commented Jul 22, 2020 at 10:52

3 Answers 3

5

What I believe you are trying to achieve is a multi-stage-build:

Stage 1: build the node app in the node container - this sould create a /dist/ directory somewhere in the container
Stage 2: Copy the built node app from the /dist/ directory to an nginx container that would serve your app.

And you are right: the problem is here COPY /dist/nexct-approval-ui /usr/share/nginx/html. This line will try to copy /dist/nexct-approval-ui from your OS, not from the container that built the /dist/ folder in Stage 1.

To refer to the image created in stage 1, try this:

COPY --from=0 /path-to-your-dist-in-the-node-container/ /usr/share/nginx/html 

In order to tell ng build to generate the /dist/ directory in a path of your choice rather than the current working directory, the --output-path can be used:

RUN node_modules/.bin/ng build --prod --output-path=/path-to-your-dist-in-the-node-container/

Credits to @user336233

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

6 Comments

Hi Neo, thanks for the answer, I think you are spot on. How do I know what the /path-to-your-dist-in-the-node-container/ is?
I think it may be the following, I am just testing it: COPY --from=0 /usr/src/app/dist/nexct-approval-ui /usr/share/nginx/html
In your case that should be /dist/nexct-approval-ui. If not try setting the value in ng build command like I suggested
@user3362334, I have set the build cmd as you suggested, but I get the same error: RUN node_modules/.bin/ng build --prod --output-path=/dist/nexct-approval-ui
Here's what's working for me: RUN ng build --configuration production --output-path=/dist when building the image and COPY --from=build /dist /usr/share/nginx/html when copying it to the NGINX
|
3

The issue was solved by user3362334 and Neo Anderson, thank you.

Here is my working solution.

# stage 1
FROM node
WORKDIR /usr/src/app
COPY package.json package.json
RUN npm install --silent
COPY . .
RUN node_modules/.bin/ng build --prod --output-path=/dist

# stage 2
FROM nginx:alpine
WORKDIR /usr/src/app
RUN rm -rf /usr/share/nginx/html/*
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=0 /dist /usr/share/nginx/html

CMD ["nginx", "-g", "daemon off;"]

Comments

2

You should check "outputPath" property in you angular.json. That's the place where the folder name that will be built inside the dist folder is specified. I guess it isn't set to nexct-approval-ui, thus the folder doesn't exist and docker throws an error.

EDIT: Another option would be to specify the output path in your build command in Dockerfile like this:

ng build -prod --output-path=[your path here]

6 Comments

It is set to: "outputPath": "dist/nexct-approval-ui",
If I change the line to the following, I still get the same error. RUN node_modules/.bin/ng build --prod --output-path=/dist/nexct-approval-ui. Because it's the same location. I think the issue is because of the prepended /var/lib/docker/tmp/docker-builder782794717. But I am not sure how to fix this.
If I look in the created images, there is no /var/lib/docker directory.
Thank you that worked, in conjunction with your recommendation above. So I chenged to RUN node_modules/.bin/ng build --prod --output-path=/dist and COPY --from=build /dist /usr/share/nginx/html.
aha, the reason for that is that I had 'FROM node:12-alpine as build' on top of my Dockerfile, so I mapped the container to name build, in your case 0 works, because it's the default name
|

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.