Your first container on Cycle — a novice’s guide to container deployment
Have you set up your first hub on Cycle? If not here’s a video walkthrough to get you started.
This guide will cover:
- Pulling a ReactJS application from GitHub.
- Packaging that application into a Docker container.
- Pushing the image to DockerHub.
- Importing the image to Cycle.
- Deploying the application and visiting it from the web browser.
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:
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.
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
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.
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.
You’ll need a DockerHub account for this, please visit DockerHub if you don’t already have one set up.
- Move to the root directory of the application.
- Find the file named
- Open the
The main difference between
Dockerfile.dev is the way we build the container.
npm build to build the source and then uses NGINX to serve the static page(s).
Another big difference between the
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 .
-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.
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
localhost and see your running application.
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
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 (
- In the “Tag” field, enter the tag
- Click “Import”.
When your image finishes importing you can use it to build a container in your environments.
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.
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
- The “Stateful” dropdown should be
- 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
- Select “Create Your Container”.
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.
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.
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.