title: Serving Angular 10 app in Docker via NGINX
body: <p>I am trying to deploy an Angular 10 web app in Docker using NGINX, but I cannot get it to be served by it. Googling around I found a lot of sparse information, but I came up with this procedure:</p>
  <ol>
  <li><p>normally <strong>build the Angular app</strong> for production (<code>--prod</code>), outside Docker. The result gets saved into the <code>dist</code> folder of the project, which then will be copied into a container. I found other examples which use multi-stage build inside the container; but this is discouraged for scalability purposes. At any rate, building the app manually gives me easier control on the result, so to me this is the way to go.</p>
  </li>
  <li><p>provide a <strong>Dockerfile</strong> using <code>nginx:alpine</code>, where I just copy a custom configuration and my compiled app to the container, and then run it as an executable via <code>ENTRYPOINT</code>:</p>
  </li>
  </ol>
  <pre><code>FROM nginx:alpine
  
  COPY nginx.conf /etc/nginx/nginx.conf
  
  WORKDIR /usr/share/nginx/html
  COPY dist/myapp/ .
  
  ENTRYPOINT [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]
  </code></pre>
  <p>This way, NGINX log should be redirected to the console, and thus shown in the container's terminal.</p>
  <ol start="3">
  <li>the meat here is in the <strong>NGINX configuration</strong> file. I don't know much about it, but from the evidence at <a href="https://blog.codecentric.de/en/2019/03/docker-angular-dockerize-app-easily/" rel="nofollow noreferrer">https://blog.codecentric.de/en/2019/03/docker-angular-dockerize-app-easily/</a> and <a href="https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/" rel="nofollow noreferrer">https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/</a>, I came up with this, which should correctly take HTML 5 routing into account (<code>nginx.conf</code>, saved in the same folder of the <code>Dockerfile</code>):</li>
  </ol>
  <pre><code>worker_processes  1;
  
  events {
      worker_connections  1024;
  }
  
  http {
      server {
          listen 80;
          server_name  localhost;
  
          root   /usr/share/nginx/html;
          index  index.html index.htm;
          include /etc/nginx/mime.types;
  
          gzip on;
          gzip_min_length 1000;
          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;
  
          location / {
              try_files $uri $uri/ /index.html;
          }
      }
  }
  </code></pre>
  <p>(I also found this <a href="https://medium.com/bb-tutorials-and-thoughts/how-to-serve-angular-application-with-nginx-and-docker-3af45be5b854" rel="nofollow noreferrer">other post</a>, but it has a less complete configuration for Angular's purposes).</p>
  <ol start="4">
  <li><strong>build</strong> the image (<code>docker build . -t myrepo/myapp:tag</code>). When doing so, it took a lot of time for sending useless content outside the <code>dist</code> folder. Thus, following a tip at <a href="https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/" rel="nofollow noreferrer">https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/</a> (&quot;optimizing the build&quot;), I added a .dockerignore with:</li>
  </ol>
  <pre><code>e2e
  node_modules
  src
  </code></pre>
  <p>This time, the build was much faster. In both cases it was successfully built.</p>
  <p>I can now <strong>run</strong> the container, either directly (<code>docker run -d -p 4200:80 myrepo/myapp:tag</code>), or from a docker compose script. In both cases, I will need to <em>redirect the container's port 80</em> (NGINX) to the host port 4200 (the usual Angular app localhost port).</p>
  <p><strong>The problem</strong>: I'd expect to see my app served by NGINX at <code>localhost:4200</code>. Instead, what I find is just the default welcome NGINX page, telling me that the NGINX server is successfully installed and working, but further configuration is required.</p>
  <p>I looked for something in the <em>logs</em>, but <code>docker logs mycontainer</code> displayed nothing.</p>
  <p>I tried to inspect the container's <em>filesystem</em> to see if the Angular app is in its place (<code>usr/share/nginx/html</code>). To this end, I followed the advice at <a href="https://stackoverflow.com/questions/20813486/exploring-docker-containers-file-system">Exploring Docker container&#39;s file system</a>: for the alpine image there is no bash, so I dumped the filesystem into a TAR file with <code>docker export mycontainer &gt; mydump.tar</code>. By looking at the TAR's content I can see that my app files are there: <code>index.html</code>, JS files, assets, and the like.</p>
  <p>What am I missing here to complete the NGINX configuration and get my app served?</p>
  <p><strong>UPDATE</strong></p>
  <p>I followed @Derek's directions: deleted <code>.gitignore</code>, replaced my <code>nginx.conf</code> with the suggested one, rebuilt the app, and run it. This time the build took about 15 minutes, and sent 1.134 GB of build context to the Docker daemon.</p>
  <p>To quickly run it in my test machine I published the image in the Docker Hub. The whole project is open source, so if anyone wants to diagnose something in a repro environment there is both the binary image and its source:</p>
  <ul>
  <li>image: <code>vedph2020/cadmus_web:1.0.5</code> (<code>1.0.4</code> is the one with my nginx). Just use the <code>docker-compose.yml</code> there, with tag <code>1.0.5</code> for the <code>cadmus-web</code> service. There is some backend stuff there, but I am sure it works because I can connect to its endpoint at localhost:60380/swagger.</li>
  <li>repository: <a href="https://github.com/vedph/cadmus_web" rel="nofollow noreferrer">https://github.com/vedph/cadmus_web</a> (the real app name is <code>cadmus_web</code>; thus the build was <code>docker build . -t vedph2020/cadmus_web:1.0.5</code>).</li>
  </ul>
  <p>Meantime I tried to create an empty dummy Angular app, and use my original Dockerfile and nginx files. To my surprise it worked. The only difference is that the dummy Angular app had no routing, whereas mine has it with <em>hash location</em> strategy. Supposing some hash-related config issue in NGINX, I tried to access mine from <a href="http://localhost:4200/#/home" rel="nofollow noreferrer">http://localhost:4200/#/home</a>, with no luck: same welcome page.</p>