In this Angular Docker Example, we will take an existing Angular 6 application and run it in a Docker container. We will show, how to create a Docker image in a modern two-stage process. We then will spin up the application in a corresponding Docker container. After that, we will save your work by pushing the project and the Docker image to GIT and Docker Hub, respectively.
The step-by-step instructions below apply to any Angular CLI projects and have been tested on Angular 4 and Angular 6.
tl;dr
In this section, we summarize the process of creating a Docker image from an Angular project within a few lines. The more elaborate version starts with the Prerequisites section below.
On a Docker host with >= 1.5 GB RAM, perform:
git clone <yourproject> cd <yourproject> curl https://raw.githubusercontent.com/oveits/angular4-docker-example/master/Dockerfile -o Dockerfile mkdir nginx curl https://raw.githubusercontent.com/oveits/angular4-docker-example/master/nginx/default.conf -o nginx/default.conf docker build -t mytag docker run -p80:80 mytag
Now access the application via a browser on http://<ip-of-docker-host>:
Done.
Prerequisites
- Docker Host with 2 GB RAM and Docker Version 17.05
- Git installed
Test Environment
- CentOS 7 image on Hetzner Cloud with 4 GB RAM
- Docker version 18.01.0-ce, build 03596f5 (minimum 17.05)
Step 0: Access a Docker Host
The Docker host must provide you with more than 1.5 GB free RAM. Since we will use a two-stage Dockerfile, the minimum Docker version is 17.05.
Step 1: Clone GIT Project
If you do not apply the instructions on your own project, you can clone the GIT project. In our example, we will apply the instructions on the Angular Tour of Heroes GIT project of John Papa:
git clone johnpapa/angular-tour-of-heroes # optional: git checkout c6596771 # so, you use the same example as I did
Step 2: Copy Dockerfile and Nginx Config File
We now need to download the Dockerfile and the Nginx configuration file into your project:
cd angular-tour-of-heroes curl https://raw.githubusercontent.com/oveits/angular4-docker-example/master/Dockerfile -o Dockerfile mkdir nginx curl https://raw.githubusercontent.com/oveits/angular4-docker-example/master/nginx/default.conf -o nginx/default.conf
Step 3: Build Docker Image
We now can build the Docker image. For convenience, we have tagged the image with a temporary tag „myimage“:
docker build . -t myimage Sending build context to Docker daemon 1.108MB Step 1/12 : FROM node:8-alpine as builder ---> ca148a52ea10 Step 2/12 : COPY package*.json ./ ---> Using cache ---> 9dbbc06fae59 Step 3/12 : RUN npm set progress=false && npm config set depth 0 && npm cache clean --force ---> Using cache ---> e87f54fe705b Step 4/12 : RUN npm i && mkdir /ng-app && cp -R ./node_modules ./ng-app ---> Running in e447c7c49bf1 npm WARN notice [SECURITY] timespan has the following vulnerability: 1 low. Go here for more details: https://nodesecurity.io/advisories?search=timespan&version=2.3.0 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] stringstream has the following vulnerability: 1 moderate. Go here for more details: https://nodesecurity.io/advisories?search=stringstream&version=0.0.5 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] randomatic has the following vulnerability: 1 low. Go here for more details: https://nodesecurity.io/advisories?search=randomatic&version=1.1.7 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] tunnel-agent has the following vulnerability: 1 moderate. Go here for more details: https://nodesecurity.io/advisories?search=tunnel-agent&version=0.4.3 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] hoek has the following vulnerability: 1 moderate. Go here for more details: https://nodesecurity.io/advisories?search=hoek&version=2.16.3 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] https-proxy-agent has the following vulnerability: 1 high. Go here for more details: https://nodesecurity.io/advisories?search=https-proxy-agent&version=1.0.0 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] http-proxy-agent has the following vulnerability: 1 high. Go here for more details: https://nodesecurity.io/advisories?search=http-proxy-agent&version=1.0.0 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. npm WARN notice [SECURITY] debug has the following vulnerability: 1 low. Go here for more details: https://nodesecurity.io/advisories?search=debug&version=2.2.0 - Run `npm i npm@latest -g` to upgrade your npm version, and then `npm audit` to get more info. > uws@9.14.0 install /node_modules/uws > node-gyp rebuild > build_log.txt 2>&1 || exit 0 > node-sass@4.9.0 install /node_modules/node-sass > node scripts/install.js Downloading binary from https://github.com/sass/node-sass/releases/download/v4.9.0/linux_musl-x64-57_binding.node Download complete Binary saved to /node_modules/node-sass/vendor/linux_musl-x64-57/binding.node Caching binary to /root/.npm/node-sass/4.9.0/linux_musl-x64-57_binding.node > node-sass@4.9.0 postinstall /node_modules/node-sass > node scripts/build.js Binary found at /node_modules/node-sass/vendor/linux_musl-x64-57/binding.node Testing binary Binary is fine > @angular/cli@6.0.0 postinstall /node_modules/@angular/cli > node ./bin/ng-update-message.js npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.3 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) added 1190 packages in 41.51s Removing intermediate container e447c7c49bf1 ---> 1d74657b3668 Step 5/12 : WORKDIR /ng-app Removing intermediate container 036674cd61f3 ---> a6bece3fd503 Step 6/12 : COPY . . ---> 9bed1d805e2a Step 7/12 : RUN $(npm bin)/ng build --prod --build-optimizer ---> Running in 41d54910ff3c Date: 2018-07-21T15:43:48.497Z Hash: 1756014f222e4d11585d Time: 42800ms chunk {0} runtime.6afe30102d8fe7337431.js (runtime) 1.05 kB [entry] [rendered] chunk {1} styles.ad4081761244032ce894.css (styles) 168 bytes [initial] [rendered] chunk {2} polyfills.0d74a55d0dbab6b8c32c.js (polyfills) 64.2 kB [initial] [rendered] chunk {3} main.043ec7c5c72f6f08b454.js (main) 405 kB [initial] [rendered] Removing intermediate container 41d54910ff3c ---> 3685c501bfe8 Step 8/12 : FROM nginx:1.13.3-alpine 1.13.3-alpine: Pulling from library/nginx 019300c8a437: Pull complete a3fe4a77433d: Pull complete a5443900e7f5: Pull complete 0ae275323c0f: Pull complete Digest: sha256:24a27241f0450b465f9e9deb30628c524aa81a1aa6936daa41ef7c4345515272 Status: Downloaded newer image for nginx:1.13.3-alpine ---> ba60b24dbad5 Step 9/12 : COPY nginx/default.conf /etc/nginx/conf.d/ ---> effb2a16266b Step 10/12 : RUN rm -rf /usr/share/nginx/html/* ---> Running in c8f0c683c752 Removing intermediate container c8f0c683c752 ---> 48141e3775a5 Step 11/12 : COPY --from=builder /ng-app/dist /usr/share/nginx/html ---> 19e7de13e9a4 Step 12/12 : CMD ["nginx", "-g", "daemon off;"] ---> Running in f11387789515 Removing intermediate container f11387789515 ---> 7cd596569ef5 Successfully built 7cd596569ef5 Successfully tagged myimage:latest
When scrolling through the log, we can see that there are many warnings, which we ignore for now.
Step 4: Run the Docker Image
Once the image has been built successfully, we can test the image by running it with a map from Docker host TCP port 80 to the container port 80:
$ docker run --rm -d -p80:80 myimage 9ad68297195068823583f563c439a6778dfce4f82aacd8fa4887bbf8b047326c
Step 5: Test the Application
We now can access the application on port 80 of the Docker host http://<ip-of-docker-host>:
That works fine.
Step 6 (optional): Push the Docker Image to Docker Hub
In order to retain your results, you may want to push the newly created Docker image to Docker hub (registration required). For that, let us re-tag the image with the correct Docker Hub user and image. First, we need to log in (type your username and password on the prompt):
docker login
Then we can re-tag the image and push the image to Docker Hub:
docker tag myimage oveits/angular-cli-hello-world-with-docker:v0.1 docker push oveits/angular-cli-hello-world-with-docker:v0.1 docker tag myimage oveits/angular-cli-hello-world-with-docker:latest docker push oveits/angular-cli-hello-world-with-docker:latest
Once, this is done, you can start the image from any other Docker host by issuing the command
docker run --rm -d -p80:80 oveits/angular-cli-hello-world-with-docker
Step 7 (optional): Save your work on GIT
If this is your own project, you also may want to retain the work by committing the changed and pushing them to GIT:
git add . git commit -m'dockerized the application' git push
Summary
We have successfully dockerized an example Angular 6 project (John Papa’s Tour of Heroes) by downloading a Dockerfile and a Nginx configuration file, building the docker image and running it.
References
- The original Dockerfile code has been borrowed from /angular4-docker-example. Many thanks to Avantsaev!
- Example Dockerfile
- Example Nginx config file nginx/default.conf
- Angular 4 Example
- Angular 4 Example for Angular Universal
Appendix A: Dockerfile
Above, we have used a two-stage Dockerfile that requires a minimum Docker version 17.05. You can download the file from here:
### STAGE 1: Build ### # We label our stage as 'builder' FROM node:8-alpine as builder COPY package*.json ./ RUN npm set progress=false && npm config set depth 0 && npm cache clean --force ## Storing node modules on a separate layer will prevent unnecessary npm installs at each build RUN npm i && mkdir /ng-app && cp -R ./node_modules ./ng-app WORKDIR /ng-app COPY . . ## Build the angular app in production mode and store the artifacts in dist folder RUN $(npm bin)/ng build --prod --build-optimizer ### STAGE 2: Setup ### FROM nginx:1.13.3-alpine ## Copy our default nginx config COPY nginx/default.conf /etc/nginx/conf.d/ ## Remove default nginx website RUN rm -rf /usr/share/nginx/html/* ## From 'builder' stage copy over the artifacts in dist folder to default nginx public folder COPY --from=builder /ng-app/dist /usr/share/nginx/html CMD ["nginx", "-g", "daemon off;"]
In stage 1, the Dockerfile spins up a NodeJS Docker container and builds the files with ng build
. Once the files are created, they are copied to the Nginx image in Dockerfile stage 2.
When starting a Docker container from the Nginx image, the Docker container will start the Nginx server.
Docker build is designed as a two-stage process; a Docker feature that requires a newer version of Docker than the one I have used for months now. With the version described above, it works, though.
Appendix B: Nginx Config
The above Dockerfile expects the default Nginx config file to be located on nginx/default.conf. Let us place it there:
$ mkdir nginx $ vi nginx/default.conf
The content of nginx/default.conf is:
server { listen 80; sendfile on; default_type application/octet-stream; gzip on; gzip_http_version 1.1; gzip_disable "MSIE [1-6]\."; gzip_min_length 256; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; gzip_comp_level 9; root /usr/share/nginx/html; location / { try_files $uri $uri/ /index.html =404; }
We have chosen to Nginx server to listen to port 80. This is, why we had to map the Docker host port to the Docker container port 80 on the docker run
command above.
Very helpful
I don’t think the title of your article matches the content lol. Just kidding, mainly because I had some doubts after reading the article. https://accounts.binance.com/de-CH/register-person?ref=UM6SMJM3
Thanks for sharing. I read many of your blog posts, cool, your blog is very good. https://accounts.binance.com/fr-AF/register-person?ref=JHQQKNKN