- [Instructor] All right let's get Jenkins
deploying our project.
So, the first thing we're going to need
is a place to deploy it.
To keep things really simple for the demo,
I'm going to go ahead and make an instance
that whenever it starts up just runs whatever is currently
on the release branch.
If you want to release a new version of your product
just tag it with the release branch
then when this service starts, it will run that.
This is a dead simple way to do
continuous deployment in Docker
and it plays very nicely with fixed server deployments
that are very common across many enterprises.
So, let's get started.
The first thing we're going to need is permission
for our instance to read our image.
So, heading on over to the IM service in the AWS console,
we go to policies and make a policy for our service.
In the interest of security,
I want this policy to be as narrow as possible.
If this server gets owned,
I don't want it to have access to anything
but the bare minimum.
So, I'm going to choose the EC2 container registry
and I'm going to choose the actions
read and list images.
Then under resources, click here
and I want to specify a specific resource.
In this case that's a particular registry
that it will have access to.
Add the resource identifier.
Now, to get this you can head over to the ECR registry,
repositories and then the example web app
and here we'll see the ARN right here.
Okay, head on back,
replace that in this box right here.
Okay, review the policy
and I'm going to call this policy production website.
Okay, now I'm going to create a role using that policy
that I can attach to my instance.
Create role, click EC2
and then EC2 again and permissions,
type production, there we are.
Now, we see the policy we just created, review
and I'm going to call this role production website.
Okay, now that we've made the role,
let's go ahead and start up an instance that uses it.
I'm going over here to the EC2 service,
the instances section
and I'm going to go ahead and launch an instance.
Again, I'm going to choose the Amazon Linux 2 LTS option.
It may say candidate for you or by the time you watch this
it may no longer say candidate, that's fine.
Then select and I'm going to choose T2 micro.
They're plenty sufficient for this service
and cheap to operate.
Configure instance details.
Now, I'm going to choose the same VPC
I've been using throughout this course.
Again, this number will be different for you,
it may just say default
and I'm going to choose the first subnet in that VPC.
I'm going to make sure auto assign public IP is enabled
and I'm going to choose the production website role
that we just created.
Okay, now down here at the very bottom, hiding in the corner
we have advanced details
and this user data section lets you type in a shell script
to run the first time this instance boots to set things up
not every time the instance boots, only the first time.
So, I'm going to go ahead and paste in a shell script here
and make that a little bigger.
Now, I understand this is a lot to type
so I'll make it available in the exercise files
for this chapter.
All right, let's go through this.
And it starts off with the usual shebang, bin bash
and then sudo yum install docker - y
so it doesn't ask any questions.
This will go ahead and install the docker package for us
then we're going to have sudo systemctl
enable docker.service
which will make sure it starts
every time this machine reboots.
The next line sudo systemctl start docker.service
ensures that it starts right now
and not just on the next reboot
then I'm going to use a little bit of shell script syntax here
to create a file.
Cat with the double left arrows next to it
and EOF means read everything until you see the letters EOF
then redirect it out into a file called start website.
This is just a handy syntax for making files quickly
from within a shell script.
So, it's going to create a file called start website
which contains the commands to start the website,
AWS ECR get login as we've seen several times so far
with the note include email and region US east one
because that's the region I'm in when I'm recording this
and that outputs the command to run to log in to Docker.
We want to actually run it so we take the output
of the command that it ran
and we pipe it to the bash command which will receive it
and run it.
And now the good part of the script,
it's going to do sudo docker run and it's going to run our image
from the release branch
and the -p 3,000 3,000 is going to expose port 3000
inside the container to port 3000 outside the container
on the host
then we reach the end of our shell script.
The next three lines are about
putting that shell script in place,
says sudo move the start website script into a location
that gets run on boot,
this is specific to Amazon's Linux AMIs
and not general to Linux as a whole,
this is an Amazon specific section here.
If you put a file in that directory on an Amazon instance
then it will get run on boot
so we need to make sure that it can be run as a shell script
by adding the chmod-X to set the executable bid on it.
Then because we'd like not to wait till the next reboot
to run this thing, we're just going to go ahead
and run the script we just created.
So, having finished that, let's move on.
Adding storage, I'll give it a little extra space
just in case, from eight to 12.
Add tags, we don't need any tags for this
and under security group I'm going to choose
create a new security group.
The default rule lets me SSH in
but I would like to also be able to serve some web traffic
and this service runs on port 3000
so I'm going to allow access to port 3000
from anywhere in the world which is 0.0.0.0/0
in amazon security group language.
Okay, review and launch.
Looks good, launch.
I select my key pair
and launch the instance.
So, now that we made a web server,
let's have Jenkins deploy our code
to this web server we just made.
Since we set up this web server to just track
whatever is on the release branch
at the time that this thing boots,
all we have to do is make Jenkins trigger a reboot
of this thing and then it will get the latest code.
But Jenkins doesn't have permission to reboot instances yet
so let's head on over to the IM service
and give Jenkins permission to reboot instances.
So, here I am in the IM service and I click on roles
and from the roles page, let me scroll down here
and click on the Jenkins role we created earlier
and then attach policies
and I'm going to attach the EC2 full access project.
This is fine for development and learning
but this is way too broad for a production service.
For a real web server, you're definitely
going to want to take the time to make a custom policy.
Okay, I clicked attach and now Jenkins has permission
to reboot instances so let's give it the code to do so.
Back here in our example web app project,
I'm going to pick up in the Jenkins file
just where we left off with the build production image
but the stage to come after building a production image
is to deploy it to a fixed server.
So, I've already put the code in here for this stage
but left it commented out.
I'm going to go ahead and uncomment that which adds a new stage
to our deployment pipeline just like that.
This stage says deploy to production on a fixed server
but we only want to deploy the release branch to production
which introduces a new type of block here,
the when condition.
We want to release production when the branch
is equal to release.
So, we put that in there
and this stage will get skipped for every other branch.
The stage is actually relatively short,
we just have a script block which says push this image
with the deploy tag just so we know what was deployed.
This is just a little bit of documentation
for our future selves so we can figure out
what is currently in deployment.
Then we run a shell script that says use the AWS command
to reboot this instance.
So, let's go ahead and save this file,
open up our project directory in the terminal
and do git add Jenkins file to add it to the next commit,
git commit -m adding deployment to fixed server.
I have too many Ms in there.
Okay, now let's go ahead and push that to release
and watch it go.
Now, that it's pushed to Github,
heading on back to our project,
in about a minute Jenkins should notice
that a new branch has appeared and kick off a build.
To see that build, click on the project name
and we see that the release branch is building.
Let's go take a look.
It made the build images.
It's running the unit tests.
The unit tests pass,
now it's building the production image
and we see it's deploying it to our production server.
All right, let's go see if it worked.
Heading back to the instance page,
I'm going to copy the Public DNS name of this instance,
open up a new tab,
paste it in and add port 3,000.
Wait a little while while it's rebooting
and there we have it, an end-to-end deployment.