Deploy your app

You'll learn
  • Setting up and running a cloud service in AWS Lightsail.
  • Pushing and deploying your app to the cloud.

The time has come! Let's deploy your app. ๐Ÿ˜Ž

We will be using AWS Lightsail for this. If you don't know, Lightsail is Amazon's beginner-friendly cloud interface. It runs on the same infrastructure as the rest of AWS, but presents a much simpler interface.

And it's definitely not just for beginners. In fact, this course site is hosted on Lightsail. I like it for its simplicity and ease of use.

The AWS account

The first thing you'll need to do is create an account with AWS, if you haven't got one already. Go to the Lightsail page and sign up or log in. And now, a disclaimer:

Important: The cloud costs real money

Let me repeat that: the cloud costs real money. The prices quoted on Lightsail are fairly low for the included package, but you can exceed the included limits and get higher charges. For example, if you start a container service for $7 a month, but use more than the included 500 GB per month of transfer, every byte transferred after that will cost you more.

I'm not saying that to scare you. It's never been easier or cheaper to get a service running on the internet, and that's absolutely great. But be careful to shut down things you don't need anymore, don't start too many things at once, and set up billing alarms to be on the safe side.

If you do end up with a larger-than-expected bill, don't panic. It has happened to me as well. AWS support is very helpful and will help you out and often refund the charge. But prevention is better than stressing over a large bill.

Okay, with that out of the way, let's create our first container service in Lightsail.

Installing awscli

We'll now be installing your new best friend: awscli, the Amazon Web Services Command Line Interface. Whew, what a name. ๐Ÿ˜…

I'm not going to lie: this is going to take some effort. So take a deep breath, complete these steps, and come back here after. I'll be waiting, and cheer on you from the sideline! ๐Ÿ•บ

  1. Go to the awscli installation instructions and follow them.
  2. Follow the guide to access Lightsail from awscli.
  3. Configure awscli to be able to access your AWS account from the command line.
  4. Install the Lightsail container plugin to be able to push container images through Docker.

In the end, you should be able to run get-container-services and get no errors:

$ aws lightsail get-container-services
{
    "containerServices": []
}

Creating the service

We will now create new container service, which is Lightsail's name for a service that runs purely with containers. That's exactly what we want. Use the create-container-service command for this:

$ aws lightsail create-container-service --service-name canvas --power micro --scale 1

This will create a new micro-sized container service with a single container running. Note that right now, this costs $10 a month, but is free for the first 3 months. Please check that this is still the case if the price is important to you.

Push your app container

We can now push the container image from before to Lightsail, using push-container-image:

$ aws lightsail push-container-image --service-name canvas --label app --image canvas

What's happening here? We ask that the Docker image canvas be uploaded to the container service canvas with the label app. Why the label? Because a container service can have multiple containers running, and they all have a name. We just have this one, and we'll call it app.

The command should print something like Refer to this image as ":canvas.app.1" in deployments in the end, which means that the container was successfully pushed to the container registry. That is the term used for the place where containers are stored in the cloud.

Deploy your container to your service

Okay, just one step missing now. We need to tell your new cloud service that this is the container we should be running. We also need to tell it the configuration options from earlier, so that the knows where to send visitors to your web app.

We will do this with create-container-service-deployment:

$ aws lightsail create-container-service-deployment --service-name canvas \
	--containers '{"app":{"image":":canvas.app.1","environment":{"HOST":"","PORT":"8080","LOG_ENV":"production"},"ports":{"8080":"HTTP"}}}' \
	--public-endpoint '{"containerName":"app","containerPort":8080,"healthCheck":{"path":"/health"}}'

What a huge command! That's because we're sending some JSON configuration objects along with it. Let's have a look.

--containers

The containers JSON object is configuration for what containers to run in our service.

  • The top-level key app is the container name.
  • image is the Docker container image name from before.
  • environment holds our app configuration as environment variables.
  • ports is a map of the open ports to the container.

--public-endpoint

The public endpoint JSON object is configuration for where the load balancer should send incoming web traffic, and how to check that the container is healthy. Remember our health endpoint? This is where it is used.

  • containerName is the container name from above.
  • containerPort is the container port from above.
  • healthCheck sets the path to our health endpoint.

Are we there yet?

Once you run the command, one of the last things printed to the console should be your app URL. Let's call it.

$ curl https://canvas.your-random-id.your-region.cs.amazonlightsail.com/
404 page not found

That has to be one of the best 404 pages you've ever seen! Congratulations, your app is now running in the cloud. ๐Ÿฅณ

Why do you get a 404? Because we only have one single handler set up, our health handler. But it's your web app serving it.

Scripting deployment

Because no one likes to remember weird deployment commands, we'll add what we have learnt to our Makefile. It has a bonus command to get the newest image, to deploy it automatically:

Makefile
.PHONY: build cover deploy start test test-integration export image := `aws lightsail get-container-images --service-name canvas | jq -r '.containerImages[0].image'` # โ€ฆ deploy: aws lightsail push-container-image --service-name canvas --label app --image canvas aws lightsail create-container-service-deployment --service-name canvas \ --containers '{"app":{"image":"'$(image)'","environment":{"HOST":"","PORT":"8080","LOG_ENV":"production"},"ports":{"8080":"HTTP"}}}' \ --public-endpoint '{"containerName":"app","containerPort":8080,"healthCheck":{"path":"/health"}}' # โ€ฆ

As always, if you don't feel like pasting this in, the changes from this section are available at

$ git fetch && git checkout --track golangdk/deploy

See the diff on Github.

For this to work, you need a nice little JSON utility tool called jq, which makes working with JSON in the terminal really easy. You'll like it.

You can now deploy a new version of your app using

$ make build deploy

If you've reached it this far, excellent! I'm proud of you. Seriously. This isn't the most exciting part of the course, but now you know how to create a new cloud service, push your app container, and deploy it to production. Wooo!

What's next? Getting rid of that 404 page, with our first real web view.

Review questions

Sign up or log in to get review questions with teacher feedback by email! ๐Ÿ“ง

Questions?

Get help at support@golang.dk.