Service updates. You've probably assumed all along that there's some way to update your services even
though we haven't been focusing on that yet.
Let's talk about it because updates has a whole lot of stuff going on under the covers. Swarm's
update functionality is centered around a rolling update pattern for your replicas. Which means if you
have a service with more than one replica, and hopefully you do, it's going to roll through them by default,
one at a time, updating each container by replacing it with the new settings that you're putting in the
update command.
A lot of people will say that orchestrators prevent downtime in updates, but I'm not going to say that
this prevents downtime.
I'm going to say it limits downtime. Because preventing downtime in any system is the job of testing.
You really need to start testing how you do your updates and determining, does it impact my users?
Does updating a database impact my web application? It probably does.
Each application that you have a service for is going to update and impact the other things around it
differently.
That's not the job of an orchestrator.
An
orchestrator can't determine that this one is a database protocol, and this one is a REST application protocol
that's easy.
So those are going to be different, complicated things that you need to deal with.
In the case of service updates, if it's just a REST API or a web frontend that's not doing anything
fancy like web sockets or long polling, if it's something very simple like that or a static website,
you'll probably have an easy update and it won't be a problem.
But other services like databases or persistent storage or anything that requires a persistent connection...
those are always going to be a challenge no matter what you're trying to update.
So test early and test often.
Like I said before, this will definitely replace containers in most updates. Unless you're updating
a label or some other metadata with the service,
it's going to roll through and change out each container with a totally new one.
Just be prepared for that. It has many options. In fact,
the last I counted, there was at least 77 options for the update command. But just about everything you
want to do can be tweaked.
A lot of the options in the update command are actually create options that just have a -rm
and a -add on the end of them. Because if it's an option that can be used for multiple values,
let's say a port to publish or an environment variable, those you can use many of them.
Right?
So, you need to be able to tell the update command which ones you're adding and which ones you're removing.
We'll see those in a minute.
This also includes rollback and health check options.
You should look at the options for those and see if their default values aren't ideal for your application
and test different settings to see if it makes an update easier for you and your system.
You also will see that we have scale and rollback options in here that are their own commands now.
They used to be options that you had to specify with the --rollback or --scale, but so many
people have been using those so frequently that Docker is now making them sort of first class citizens
in the command line.
They might be adding more of those in the future.
Lastly, before we get to some examples, if you're doing stacks, a stack deploy to the same stack is
an update.
In fact, there is no separate option for stack updates.
You just do a stack deploy with the same file that's been edited.
Then, it will work with the service commands and the networks, and every other thing it does. It will
work with them to make sure if any changes are necessary, that they get applied.
Let's look at some quick examples and then we'll get to the command line.
This one is probably the most common example that you'll be using, which is to change the image of a
service.
Every time you update your app and you build a new image, you're going to have to do a service update
command, with the image name, and then the service name.
So in this case, maybe I had my application with a tag of 1.2.0.
And in this case I'm now applying a 1.2.1 image, and the service will determine,
ah yes, that's a different image than I have running in my service,
and we'll go and update them. On this next one, we're showing how you can do multiple things at once inside
a single update command.
You can add an environment variable with the env-add, and then you can remove a port with the publish
-rm.
We could also be adding and removing environment variables and publish ports in the same update command
as much as we want. On this last one, this is showing how we can use these new scale and rollback
commands on multiple services at the same time. Which is one of the advantages of using them over the
update command is that they can apply to multiple services.
In this case, I'm actually going to be changing the number of replicas of the web and the API services
at the same time.
Like I said a while ago, in the Swarm updates, you don't have a different deploy command.
It's just the same docker stack deploy, with the file that you've edited, and it's job is to work with
all of the other parts of the API to determine if there's any changes needed,
and then roll those out with a service update.
All right. Let's start by actually creating a service so that we can manipulate it with some update commands.
docker service create -p 8088 80 name web, and we'll use Nginx, and we're going to specify a version like
we always should in production.
It's nice, now that we actually have in the last half of 2017, the detach option with our service create
and update commands, we can actually see this happen synchronously in real time.
So this will be good for update commands to see how updates actually roll out via the command line.
All right. Now, if we do a docker service ls, we see that our service is running and that it's got
1 of 1 replicas, so it's good to go.
Now let's scale our service up so we can have some more replicas to work with. docker service scale
Web=5. And you just saw that one of those was already running,
and the other 4 had to start. It went by pretty quickly on mine because I already had the image
downloaded, but yours may take a few minutes while they're in pending state as the image downloads on
the other nodes.
All right.
Let's do a rolling update by changing the image of that Nginx.
You'll see here that I've picked an older image.
Now, Docker doesn't care about what the image actually is.
It could be a completely different application
for all it cares. It just knows that in this service, I'm changing it to a different image.
Remember, by default, it's going to go through here one at a time.
It will first remove it, create a new one, and then when that one's good to go,
and it looks healthy, it'll start in the next one. In the next example, we're going to change the published
port.
But you can't change a port.
You actually have to add and remove them at the same time.
So in this case, because we first published it with an 8088, we need to do a docker Service update
publish rm 8088. I don't need to specify the value. I just need to specify the key. Then
we're going to publish the new one, 9090. Then the value, which in this case is 80. You'll see that
it will do the same update process as before.
The last example I want to talk about is kind of a tip. Because you'll often have a challenge with
something called rebalancing. Or if you change the number of nodes or if you move a lot of things around,
if you have a lot of containers in your swarm, you may find that they're not really evened out. You've
got maybe some nodes that are pretty light on how many containers are running and other ones that have
a lot. If you have a lot of things changing, Swarm will not move things around to keep everything balanced
in terms of the number of resources used.
But, what you can do is you can force an update of a service even without changing anything in that service.
Then, it will reissue tasks, and in that case, it will pick the least used nodes, which is a form of rebalancing.
A lot of times in a smaller swarm when I move something big, or add a bunch of nodes, I suddenly have
a bunch of empty servers doing nothing and I need to get work on them.
So what I'll do is take one or two of my services, and I will do a docker service update --
force, and in this case it's going to roll through and completely replace the tasks.
Of course it will use the schedule's default of looking for nodes with the least number of containers
and the least number of resources used.
That's kind of a trick to get around an uneven amount of work on your nodes.
Remember to clean up by removing the service that we created in this lecture.