Seeing modern day applications often store their state in databases or caches, horizontally scaling your web applications with technologies such as Docker becomes increasingly feasible.
You can find the code used in this article on GitHub.
What you will need:
- Recent version of Docker - at the time of writing, we used Docker CE 17.09
- Recent version of both Nodejs and npm
Once you've installed those, and you've fired up your favourite editor, we're good to go!
What we're looking to do is create a single
Dockerfile that will take our application's source, compile it, and then create a Docker image based on nginx to serve our application.
To get there, first we'll need something resembling a React app to deploy. You can either grab the one from the sample code, or use the create-react-app package to bootstrap a new, empty React app for you:
npx create-react-app sample
npx isn't available in all versions of
npm - if it doesn't work, try running:
npm install -g create-react-app create-react-app my-app
NPM will do its thing, and you'll end up with a
sample directory containing a couple of files, along with a
node_modules folder. We'll be using this directory as our working directory for the rest of this article.
Now that we've got a React app, we can build it. You can try building it locally first by
cding to your workspace directory and running
npm run build
This'll create a production build of your application which you can then serve by running
serve -s build. While this is fine for running things locally, ideally we want to use a more robust web server like nginx or Apache to serve our application in a production scenario.
We'll be creating a single
Dockerfile that contains both our builder image and the nginx image that will end up serving our application. In your app's directory, create a
Dockerfile with the following contents:
This will grab the
node image, copies our local working directory onto the image, and create a production ready build with all the artifacts we'll need to run our React app in production.
Optionally, you can try building the Docker image by running
docker build -t react-sample-app .
To see if everything up to this point is working properly. If it does, we can continue to the next bit: getting nginx set up to serve our app.
Now that we have a production ready build of our React app, we can start serving it via nginx.
We will need to let nginx know how we want to serve our application. We do this by creating a
default.conf pointing nginx at the directory we'll copy our React app to. Create a folder called
nginx in your workspace directory, and inside it, create a
default.conf file with the following contents:
Next we'll extend the
Dockerfile we created in the previous step to grab the contents of the
build directory and move it to the nginx image:
COPY --from=builder instruction we use, which indicates that we want to grab the build folder from the builder image. We'll move that folder, along with the nginx configuration file over to our final nginx image.
Building the final image
Previously, we have configured both the builder image to build our React app, and the nginx image which will end up serving it. All that's left, is building the final image we can run on our production environment.
In your working directory, simply run:
docker build -t react-sample-app .
Yes, that's the same command we ran before to build our application in a Docker container - except this time it bakes in the nginx hosting layer as well.
After that's completed, you'll end up with a
react-sample-app image containing our React app and nginx. You can see if it runs by running:
docker run -p 8080:80 react-sample-app
8080 is the port on your machine, and
80 is the port inside the container.
If all went well, you should be able to see your application running on http://localhost:8080.
Again, if you need it, you can find a working version of the code above over at GitHub.
Thanks for reading!