Building a simple Docker Image with StencilJS and Ngnix
Tags: webdev, tutorial, stenciljs, docker
Published: 2023-04-06 11:41:03


The goal is to generate a [Docker](https://www.docker.com/) image containing the production build of a web-app bundled with a web server, starting from the source code of the web-app.


## Web app 📦

The web-app is a standalone [Stencil.js](https://stenciljs.com/) application, running with the help of [Node.js](https://nodejs.org/en), and for the web server we are using [Nginx](https://www.nginx.com/).

Starting from the source code, provided we have a version of Node installed on the system, we can install the necessary dependencies using the command:

```
npm install
```

To generate the production build (with minified code) we will use the command:

```
npm run build -production
```

As we are building the project as a standalone Stencil.js application, what we are interested in is the "www" folder, as that is the relevant target for our use case. It also contains an "index.html" file which serves as the entry point to the application.
Documentation can be found [here](https://stenciljs.com/docs/www).



## Web server 🍽️

Before we move on to the Dockerfile and the docker image building process, we first have to take into account a few aspects about the web server. Our choice is Ngnix, because it is lightweight, simple to use and has extensive configuration available.

Nginx will serve our files to the end user, provided we configure it properly. The production build files (the contents of the "www" folder we presented earlier) must be placed inside the nginx folder called "html".  We also must pay attention to the "nginx.config" file, as that is where we can set up things such as which ports to use or even a proxy configuration. A full example of the configuration file contents can be found [here](https://www.nginx.com/resources/wiki/start/topics/examples/full/).



## Dockerfile 🐋

After we have the generated production build, we can focus on the Dockerfile. The Dockerfile should be placed at the root of the project. Its contents describe a series of instructions necessary for the image we are trying to create.
For the purpose of generating a simple Docker Image with Nginx and our production build we need just the following instructions in our Dockerfile: 

```
FROM nginx:alpine

COPY www/ /usr/share/nginx/html
```

As you can see we are starting from the alpine version of the nginx docker image, as it contains all the basic functionality we need for a web server, and it is also much lighter than the base nginx docker image.

After that we are copying the contents of the "www" production build folder to the "html" folder of nginx on the container. And that is it for a simple Dockerfile that will generate an image with our app and the nginx web server.

To build the image, we have to run the following command in a terminal inside the project folder, at the root:

```
docker build --rm -f Dockerfile -t nameofimage .
```

! Also don't forget about the "." at the end.

With this configuration, nginx will serve at the default port of 80, so we can use the following command to run the image into a container:

```
docker run --rm -d -p 9999:80 nameofimage
```

This will serve the internal port 80 of nginx to the external port of 9999 on localhost.


If we need a custom config for the web sever, we can create a new file at the root of the project called "nginx.config". In this file we can modify the settings for things such as ports or to set up a proxy. To apply this changes, we need to overwrite the config file that comes by default with ngnix in the container. We can do that by adding a couple of commands to our Dockerfile:

```

FROM nginx:alpine

RUN rm /etc/nginx/conf.d/default.conf

COPY nginx.config /etc/nginx/conf.d/default.conf

COPY www/ /usr/share/nginx/html
```

A more comprehensive guide can be found [here](https://levelup.gitconnected.com/deploying-your-ui-applications-using-docker-and-nginx-b65ffa8f744e).