Updated: This article is quite old now. Please visit our updated page: Using Angular with Docker and Docker Compose
Angular CLI is a great tool for developing Angular 2 applications. Now that the final 2.0 release is out and the masses are starting to be interested I thought it would be fun to do a quick demo of how you can try out the Angular CLI (github) project without having to install all the tools on your local machine. The caveat there is that I assume you already have Docker installed.
To start we need to create a Dockerfile that will have all the tools we need ready. A good example of that file might look like this
FROM node ENV HOME=/usr/src/app RUN mkdir $HOME WORKDIR $HOME RUN npm install -g angular-cli EXPOSE 4200 EXPOSE 49153
In that file we specify we want to use the current Node.js image as our base. Then we setup our home directory so our code will have a place to live. Next we use NPM (Node Package Manager) to install the Angular CLI tool chain. Then we expose the default port the Angular 2 project will be served to the browser from, and we open up the port that will be used for live reloading of code.
Next we want to create a docker-compose.yml file which will define our service we will use to execute the build commands and run our development web server iniside.
client: build: . ports: - "4200:4200" - "49153:49153" volumes: - .:/usr/src/app command: npm start
This file defines a service called “client” which will be built based on our Dockerfile we just created. We map the ports from the container onto our local machine and specify that we would like this directory mounted inside the container as a volume at /usr/src/app which is our home directory defined in the Dockerfile.
The final step is to build our image so we can use it to run containers.
docker-compose build
With our docker requirements in place we are ready to actually play with Angular CLI.
docker-compose run --rm client ng init --skip-npm --name CliDemo
docker-compose run --rm client npm install
This will run through the creation of a fresh Angular 2 project and run NPM to install all the dependencies required. The only configuration change required to this code because of our docker environment is to update the start script to bind to all interfaces. Please edit this line in our package.json file
... "start": "ng serve --host 0.0.0.0", ...
Finally we just need to start the watcher and development web server
docker-compose up
This will compile the project and start a development web server running on http://localhost:4200/. Fire up your browser and give that page a look. Congratulations! You created a fresh Angular 2 project and compiled it and ran it in your browser.
NOTE: If you are not using linux, or the new Docker Native for OSX and Windows then you will need to use the IP of your docker-machine instead of localhost in the url above.
[UPDATE: 1/1/2017] After having used this several times I have noticed that it seems to always fail on the npm install when run as part of the project generation. So I have separated those steps above. Also I added a github repo if you want to grab the files.
Quick heads up after reading the article. For this kind of Angular-CLIs, how a developer has to know if the codebase structure is optimal for a project?
I know that for example in Angular #1 there was a CLI which was doing it’s job but the code structure was not optimal in my and my colleagues eyes.
It’s always the most important question to ask – if the structure will work for me or not?
Hi Kamil,
In regards to your question, the truth is that you will probably need to work with an Angular 2 project to find out if the structure of the application is one you will find useful. Before Angular CLI was released I was using another “starter” project for Angular 2 projects. This project worked great but had quite a few configuration files and dot files to make it successful. Angular CLI has abstracted many of those making the project much cleaner, while providing a single configuration file that allows you to do most of what you needed all the other files.
Specifically when you a generate a new project using Angular CLI there are 6 files at the root of the project (package.json, tslint.json and such) and 2 folders e2e (testing configuration files) and src. Once you run `npm install` you will also have a node_modules directory. The src directory is where all the code for your project will live and I have been very happy with the layout.
In addition to creating a new site, Angular CLI also includes the ability to generate components, directives and all the other types of classes and templates required to build Angular 2 applications. These get generated using standard conventions laid out in the Angular 2 style guide. So I think they are a great tool for ensuring your team has greater interoperability with other developers using Angular 2.
Simeon,
First off, thanks for the great tutorial! However, I am getting stuck at [docker-compose run –rm client ng init –name CliDemo]. When running that command, I get “Package install failed, see above” returned. I called my repository “ngtodos” and “ngtodos_client” exists after running [docker-compose build]. I can’t figure out what is causing that error in the [docker-compose run] command. Hopefully you ran into this or have some ideas on how to resolve it.
Thanks in advance!
Hi Donald,
I just tried to run through the example again and it failed for me as well. It appears that npm is having some trouble with permissions (at least in my state). I am wondering if this has to do with github making changes after they were part of the DDOS today.
I’ll take a look and see if I can resolve this.
For what its worth, the files for your project should have been generated if you are getting installation problems. Which means you can try to finish installing the dependencies by running “npm install” inside the container. With docker compose that command looks like
docker-compose run –rm client npm install
I’m experiencing the same error — tried so many different things, nothing seems to be resolving it.
I tried different versions of node, npm..same result..I wonder what is causing it.
Hi Traz,
I ran through the instructions in this post again this morning. Without altering anything from the steps above, I found that the initial install of the modules as part of the angular cli setup failed. But running the command `docker-compose run –rm client npm install` installed all dependencies without issues. I was then able to run `docker-compse up` and browse to http://localhost:4200/ to see the application running as intended.
Docker version 1.12.5, build 7392c3b
docker-compose version 1.9.0, build 2585387
I have updated the steps to separate generating the project files and installing the dependencies from NPM. For some reason this seems to fail on a pretty regular basis when combined.
Hi thanks for this awesome tutorial. This is working absolutely fine but livereloading is not working. I also noticed that server is not restarting on change of files. Helpppppppp meeker please.
Hi Karthikeyan,
I am glad you have found the tutorial useful! I am not having any issues with live reloading or the save to rebuild features. We are exposing the port that allows the live reloading to work.
If you are running the older docker the filesystem may not be able to detect the changes in the volume. I am running docker native 1.12.5 and everything is happy to go.
If you are not able to upgrade your docker installation, there is an option you can add to angular-cli.json to enable polling. In the defaults section of your angular-cli.json add `”poll”: 1000,`. If you are running a current version of angular-cli (which we should be based on this tutorial) this should enable polling every second and allow the detection of changes.
Good Luck!
Thanks its working! May i know how do i run this in prod mode?
i jus replaced ng –serve with ng build but dint work :(.
You don’t actually run angular-cli “in production”. However you can build the output for production and then put it on a server.
To do this you would want to execute the build:
docker-compose run –rm client npm run build
This should place all the generated and minified files in the dist directory. You can then upload them to wherever you like.
thanks that all worked like charm. may i know how to run this with watcher mode?
Hi Kartik,
You dont typically run the production build in watcher mode. You build normal and then when you want to you output for production. I don’t believe ng-cli has a watcher for the production build. You might want to look more into their docs.
i don wont want to run ngcli in production. it takes a lot of time to see the changes i make. should i enable watcher mode, to reload the page faster than the default one?
Hi Simeon,
Great tutorial, thanks. It was crystal clear. I also needed the special piece of knowledge about the ‘poll’ option to add inside the .angular-cli.json file. I’m also working on Win 7, and my changes were not detected inside the container. So I searched, and ended up on these links : https://github.com/angular/angular-cli/pull/1814 (which explains the problem) and https://github.com/angular/angular-cli/blob/master/docs/documentation/angular-cli.md, which explains where to put exactly the ‘poll’ option inside the .angular-cli.json file.
I tested the functionality, and it worked !
What a nice tutorial! Thanks i reallly enjoyed your tutorial. can you please tell me, how can i run angular cli in production?
I think what you are looking for is executing the build command:
docker-compose run –rm client npm run build
I’m having problems with installing angular-cli normally and creating my project with “ng new projectname”, but I create my project in a folder that generated a volume in the container, when I change directly through the linux container, ng serve updates the file, however When I change by windows on volume it does not update the application;
Sometimes with docker machine or with older docker native installs, the filewatcher in node.js can not detect file system changes on the volumes. So there are two things to look at, when you modify the files from inside the running docker container are those changes reflected on your host system? If not then there is likely something wrong with your volume mapping. If you do see those changes in the host system then its likely the issue with node.js not detecting the files system changes. In which case you either need to update to the latest docker native (preferred) or enable polling in your angular cli config. Polling will be slower because it checks for changes on an interval rather than using the file change events. Good Luck!
I’m creating my container with the command below
docker run -dt -p 4200:4200 -p 49153:49153 -v /c//Documents:/var/www/frontend/ –name angular ubuntu:16.10
I install nodejs and angular-cli, typscript with the npm commands, I can run ng -host serve -host 0.0.0.0 and see application normally, if I change through nano directly in the container updates normally, but if I change in my windows volume is not Reflected in the application
Ok, well I totally recommend using docker-compose for making it easy to run reproducible builds and not having to manage docker state on your own. When you make changes inside the container using nano do you see the changes in the files on your windows machine?
Thanks Simeon.
build was successfull. but when i tried to run docker-compose run –rm client ng init –skip-npm –name CliDemo
I got an error ERROR:Cannot start service cpanel_client: invalid header field value “oci runtime error: container_linux.go:247: starting container process caused “exec: \”sudo\”: executable file not found
Do you have any idea?
I got error with `docker-compose build`
I starts ok and after a while it enters a loop and keeps printing:
`gyp WARN EACCES attempting to reinstall using temporary dev dir “/usr/local/lib/node_modules/angular-cli/node_modules/node-sass/.node-gyp”
gyp verb tmpdir == cwd automatically will remove dev files after to save disk space
gyp verb command install [ ‘8.4.0’ ]
gyp verb install input version string “8.4.0”
gyp verb install installing version: 8.4.0
gyp verb install –ensure was passed, so won’t reinstall if already installed
gyp verb install version not already installed, continuing with install 8.4.0
gyp verb ensuring nodedir is created /usr/local/lib/node_modules/angular-cli/node_modules/node-sass/.node-gyp/8.4.0
gyp WARN EACCES user “nobody” does not have permission to access the dev dir “/usr/local/lib/node_modules/angular-cli/node_modules/node-sass/.node-gyp/8.4.0”
`
Do you have any idea?
Hello,
I’m having the same issue. Did you ever solve this?
Thanks.
Hi, Paweł. I have same problem. Did you solve it?
Thanks. This is still working like a charm. May I know how to run ‘ng build –prod –app 1’
The above command is to create angular universal bundle. How do I create it using docker-compose up?
Hi Karthikeyan,
Using docker-compose you can run arbitrary commands inside the context of the container.
So you can type something like this:
docker-compose run –rm client ng build -prod -app 1
Although I would recommend adding that command as a script inside your package.json then calling that script from the run command instead.