Your First Website on Cycle - Using React and Nginx to Serve a Static Website

Christopher Aubuchon
cycleplatform
Published in
8 min readSep 24, 2019

Hello! Our blog has moved to our website you can find this article and many others here.

This guide will cover:

  1. Pulling a ReactJS application from GitHub.
  2. Packaging that application into a Docker container.
  3. Pushing the image to DockerHub.
  4. Importing the image to Cycle.
  5. Deploying the application and visiting it from the web browser.

Have you set up your first hub on Cycle? If not here’s a video walkthrough to get you started.

But First, Why Containers?

Developing and maintaining software for the cloud has traditionally been a major challenge. We’ve gone from shared hosting, where everything is just installed onto a server at the top level, to Virtual Machines (VMs), where we take a beefy server and chop it up (via software) into smaller, virtualized computers that have a significant amount of isolation built into them, allowing for sharing a server without ever knowing anyone else is running on the same physical machine. Containers are the next step in this evolution.

A container, at its core, is really just a process with some restrictions on it. It runs on the host, but uses features of the Linux kernel to isolate it so that it appears to be the only process running on the machine (among some other isolations, such as network). This is advantageous for a few reasons. First, we get all the benefits of using the host machine — not much overhead, and the container is able to run on the real hardware instead of jumping through virtualized hoops. Second, we get many, if not all of the benefits of virtualization — isolated processes, resource caps, and a sterile, reproducible environment for our applications.

Another premier feature of using containers is the ability to run them anywhere regardless of the underlying OS, packages, versions, or anything else for that matter, whether it’s on your local machine or in the cloud with a platform like Cycle. So this article will not make any assumptions other than:

  1. The system has Docker installed.
  2. You’re able to pull a repo from Github.

With Docker, you could buy a computer, install git, a code editor and immediately have a dev environment capable of working with any language.

That's pretty great, so let’s dive right in.

Getting the files

Pull this repo into a new directory (doesn’t matter what it’s named).

This repo is the same collection of files you receive when running the following command, plus a few QOL add-ins:

npx create-react-app appname

There is a file named devscript included in the repo. To execute this file enter the following into your command line from the applications root directory, ./devscript.sh. This script builds an image named firstreactapp using Dockerfile.dev. It also runs the image with a bind mount on the applications src directory, allowing for hot reloading*. Take a look inside the script if you want to see the commands I’m running to automate these steps.

* Hot reloading means your application reloads after you make changes to the source without needing to rebuild the image and restart the container.

Hot reload is set up on the src folder, as that's what I make changes to the most during dev. If you make changes to other files, outside of src — just stop the container that’s running with ctrl + c and run the devscript again to rebuild the image and restart the container.

Run the devscript and make any changes you want to the React app. When you’re happy with your app, shut down the development container with crtl + c.

Let’s get ready to build a production image.

You’ll need a DockerHub account for this, please visit DockerHub if you don’t already have one set up.

Building the production image

  • Move to the root directory of the application.
  • Find the file named Dockerfile (not Dockerfile.dev).
  • Open the Dockerfile.

The main difference betweenDockerfile and Dockerfile.dev is the way we build the container. Dockerfile uses npm build to build the source and then uses NGINX to serve the static page(s).

Another big difference between theDockerfile and Dockerfile.dev is the two FROM statements in Dockerfile. When Docker sees two FROM statements, it knows that you want a multi-stage build. You can learn more on multi-stage builds here.

Let’s use the Dockerfile to build our new image.

docker build -t username/firstreactapp:latest -f Dockerfile .

Using the -t flag with docker build allows us to name the image in a way that complies with what DockerHub will expect when we need to push to our registry. It’s important to note that the tag latest is not a part of the image name. It’s actually a tag representing meta information about the image.

You can find more info on tags here.

Using docker run we can test that our image is working as expected. Use the following command to run the new image.

docker run -p 80:80 username/firstreactapp:latest

Now visit localhost and see your running application.

A basic react up being served by NGINX.

Pushing to DockerHub

To log into DockerHub through the Docker CLI, head back to your terminal and enter docker login. You should be greeted by a dialog asking for your username and password. Entering those credentials will allow you to push and pull images from your DockerHub registry.

Once you’ve logged in, you can run the following command to push the image we just created to your personal DockerHub registry:

docker push username/firstreactapp:latest

Pulling your image to Cycle

So far we’ve created a local development image, made changes to our base application, and built a production ready image that was pushed to your DockerHub registry.

Now we can log into Cycle and pull our image into our Hub.

  • Log into your Cycle hub.
  • Select “Images” from the left-hand nav.
  • Click “Import Image” in the top right corner of the screen.

When importing your image make sure to select “Docker Hub” from the registry options. If you’d like to find out how to create your own private Docker registry using Cycle check out this article.

  • In the “Image Name” field, enter your full image name ( username/firstreactapp).
  • In the “Tag” field, enter the tag latest.
  • Click “Import”.

When your image finishes importing you can use it to build a container in your environments.

Deploy your image

Create an Environment

If you’ve never created an environment, following this guide can help you get started in just a few steps.

The environment we are going to create today needs to have legacy networking enabled in order to work with the official nginx:latest image. Legacy networking tells Cycle to enable IPv4 support. Cycle’s native network settings are IPv6 by default, but many apps don’t support IPv6 out of the box. So, it’s simpler to be verbose about the expectations of the environment.

Make sure to enable legacy networking.

Create the container

After creating your environment, click the blue “Deploy Container” button on the top right of the screen. You’ll be taken to the container wizard where you can describe the settings for the container and tell Cycle which image you want to use.

  • In the “Container Name” field enter firstreactapp.
  • The “Stateful” dropdown should be stateless.
  • Leave “Starting Instance Count”, “Deployment Strategy”, “Tags (Any)”, and “Tags (All)” with their default settings.
  • Click the “Use Existing” box under “Image” and then use the dropdown menu to select your image.
  • Set the “Public Network” field to Enabled.
  • Select “Create Your Container”.

Start the Environment

Now that our container has been created we can navigate back to the environment dashboard and start our environment. To find the environment dashboard click the name of the environment near the top of the page. From here you can start the environment by holding down the start button.

Navigate to the environment dashboard and then start the environment.

Once the environment is started you can navigate back to the container dashboard and use the domain provided by Cycle to access your container.

Note: When starting your environment for the first time it may take up to 10 minutes for the domain to be recognized by DNS servers, please be patient.

And that’s all it takes to deploy a React application to Cycle! Let’s do a quick recap of what we accomplished.

  • Created a development container to work with while we changed our code.
  • Created a production container that used a static build of our application and served it with NGINX.
  • Pushed the production image to DockerHub.
  • Pulled the production image into our Cycle hub.
  • Created a container from our image in our environment.
  • Viewed our application in a browser using a URL.

Still Have Questions?

If you want to dive in and learn more, head over to our slack channel. Our community is growing, and our team hangs out there daily. Feel free to shoot us a message any time with your questions and we’ll be sure to respond!

Of course, for a more in-depth look at how to use Cycle, check out our documentation.

Learn More + Get Started Today

Thanks for checking out our blog! If you like what you read, please subscribe.

To learn more about Cycle, please visit https://cycle.io.

To create a free account, check out our portal!

--

--

Christopher Aubuchon
cycleplatform

Producing Content for Cycle.io to help keep your life in the cloud simpler.