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 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:
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.
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! ๐บ
In the end, you should be able to run get-container-services and get no errors:
$ aws lightsail get-container-services
{
"containerServices": []
}
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.
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.
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.
The containers JSON object is configuration for what containers to run in our service.
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.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.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.
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
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.
Get help at support@golang.dk.