How to use docker service create command to deploy and manage services

DockerDockerBeginner
Practice Now

Introduction

In this lab, you will gain hands-on experience using the docker service create command to deploy and manage services within a Docker Swarm. You will learn how to create and inspect different types of services, including simple replicated services for high availability and scalability, and global services that run on every node.

Furthermore, you will explore advanced service configurations such as implementing rolling update policies for seamless deployments, utilizing bind mounts and environment variables for data persistence and configuration, and applying placement constraints and preferences to control where your service tasks run within the swarm. By completing these steps, you will develop a solid understanding of how to effectively manage containerized applications in a Docker Swarm environment.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ls("List Containers") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") subgraph Lab Skills docker/run -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/ls -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/ps -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/exec -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/inspect -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/create -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} docker/pull -.-> lab-555224{{"How to use docker service create command to deploy and manage services"}} end

Create a simple replicated service

In this step, you will learn how to create a simple replicated service in Docker Swarm. A replicated service is a service that runs multiple identical tasks across the swarm. This provides high availability and scalability.

First, let's make sure Docker is running and you are in the correct directory.

docker version
pwd

You should see output indicating the Docker version and your current directory as /home/labex/project.

Before creating a service, we need to pull the necessary Docker image. We will use the nginx image for this example.

docker pull nginx:latest

This command downloads the latest version of the nginx image from Docker Hub.

Now, let's create a simple replicated service named my-nginx-service with 3 replicas.

docker service create --name my-nginx-service --replicas 3 nginx:latest

This command creates a new service named my-nginx-service using the nginx:latest image and sets the number of desired replicas to 3. Docker Swarm will then distribute these 3 tasks across the available nodes in the swarm.

To check the status of the service and its tasks, you can use the docker service ls and docker service ps commands.

docker service ls
docker service ps my-nginx-service

The docker service ls command lists all services running in the swarm, showing their ID, name, mode, replicas, and image. The docker service ps my-nginx-service command shows the tasks associated with the my-nginx-service, including their state (e.g., Running, Shutdown), desired state, and the node they are running on. You should see 3 tasks in the "Running" state.

Create a global service and inspect its tasks

In this step, you will learn how to create a global service in Docker Swarm. Unlike replicated services which run a specified number of tasks, a global service runs exactly one task on every node in the swarm that meets the service's constraints. This is useful for services like monitoring agents or log collectors that need to run on every node.

We will use the busybox image for this example. Let's pull the image first.

docker pull busybox:latest

This command downloads the latest version of the busybox image.

Now, let's create a global service named my-global-service.

docker service create --name my-global-service --mode global busybox:latest sleep infinity

This command creates a new service named my-global-service using the busybox:latest image. The --mode global flag specifies that this is a global service. The sleep infinity command is used to keep the container running indefinitely.

To inspect the tasks of the global service, you can use the docker service ps command.

docker service ps my-global-service

This command will show the tasks associated with my-global-service. Since this is a global service, you should see one task running for each node in your swarm. In this Lab environment, you will likely see only one task as there is only one node. The output will show the task's state, desired state, and the node it is running on.

You can also inspect the service configuration using the docker service inspect command.

docker service inspect my-global-service

This command provides detailed information about the service, including its mode, replicas (which will be 0 for a global service in the service list, but the docker service ps will show tasks per node), and other configuration details.

Create a service with replicas and rolling update policy

In this step, you will learn how to create a replicated service and configure its rolling update policy. Rolling updates allow you to update your service to a new version without downtime by gradually replacing tasks with the new version.

We will continue using the nginx image. Let's create a replicated service named my-nginx-update-service with 5 replicas and a rolling update policy.

docker service create \
  --name my-nginx-update-service \
  --replicas 5 \
  --update-delay 10s \
  --update-parallelism 2 \
  nginx:latest

This command creates a service with the following configurations:

  • --name my-nginx-update-service: Sets the service name.
  • --replicas 5: Sets the desired number of replicas to 5.
  • --update-delay 10s: Sets the delay between updating each group of tasks to 10 seconds.
  • --update-parallelism 2: Sets the number of tasks to update simultaneously to 2.

These update parameters define how the service will be updated when you deploy a new version of the image. Docker Swarm will update 2 tasks at a time, waiting 10 seconds before updating the next batch.

You can check the service status and its tasks using the docker service ls and docker service ps commands.

docker service ls
docker service ps my-nginx-update-service

You should see my-nginx-update-service listed with 5/5 replicas and the tasks in the "Running" state.

Now, let's simulate an update by changing the image to a different version. We will use the nginx:1.21 image. First, pull the image.

docker pull nginx:1.21

Now, update the service to use the nginx:1.21 image.

docker service update --image nginx:1.21 my-nginx-update-service

This command initiates a rolling update. Docker Swarm will start replacing the nginx:latest tasks with nginx:1.21 tasks according to the --update-parallelism and --update-delay settings you configured earlier.

You can observe the rolling update process by repeatedly running docker service ps my-nginx-update-service.

docker service ps my-nginx-update-service

You will see tasks transitioning from "Running" with the old image to "Shutdown" and then new tasks starting with the new image and entering the "Running" state. The update will happen in batches of 2 tasks with a 10-second delay between batches.

Create a service with bind mounts and environment variables

In this step, you will learn how to create a service that uses bind mounts to persist data and environment variables to configure the application inside the container. Bind mounts allow you to mount a file or directory from the host machine into a container, making the data accessible to the container and persistent even if the container is removed. Environment variables are a common way to pass configuration information to applications.

First, let's create a directory on the host machine that we will bind mount into the container.

mkdir -p ~/project/html

This command creates a directory named html inside your ~/project directory.

Now, let's create a simple HTML file inside this directory.

echo "<h1>Hello from Bind Mount!</h1>" > ~/project/html/index.html

This command creates a file named index.html in the ~/project/html directory with the content "

Hello from Bind Mount!

".

We will use the nginx image again. Let's create a replicated service named my-nginx-volume-service with 1 replica, binding the ~/project/html directory to the default Nginx webroot directory inside the container (/usr/share/nginx/html), and setting an environment variable.

docker service create \
  --name my-nginx-volume-service \
  --replicas 1 \
  --publish published=8080,target=80 \
  --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html \
  --env MY_VARIABLE=hello \
  nginx:latest

Let's break down the new options:

  • --publish published=8080,target=80: This maps port 8080 on the host to port 80 inside the container, allowing you to access the Nginx web server from your host machine.
  • --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html: This creates a bind mount. type=bind specifies the mount type. source=/home/labex/project/html is the path on the host machine. target=/usr/share/nginx/html is the path inside the container where the host directory will be mounted.
  • --env MY_VARIABLE=hello: This sets an environment variable named MY_VARIABLE with the value hello inside the container.

Check the service status and tasks:

docker service ls
docker service ps my-nginx-volume-service

Wait for the task to be in the "Running" state.

Now, you can access the Nginx web server running in the container by visiting http://localhost:8080 in a web browser or using curl.

curl http://localhost:8080

You should see the content of the index.html file you created: <h1>Hello from Bind Mount!</h1>. This confirms that the bind mount is working correctly.

To verify the environment variable, you can execute a command inside the running container. First, find the task ID of the running service.

docker service ps my-nginx-volume-service

Note the Task ID from the output. Then, use docker exec to run a command inside the container. Replace <task_id> with the actual Task ID.

docker exec < task_id > env | grep MY_VARIABLE

This command executes the env command inside the container associated with the task ID and pipes the output to grep MY_VARIABLE to find the environment variable. You should see MY_VARIABLE=hello in the output.

Create a service with placement constraints and preferences

In this step, you will learn how to use placement constraints and preferences to control where your service tasks are deployed within the Docker Swarm. Placement constraints are hard requirements that a node must meet for a task to be scheduled on it. Placement preferences are soft requirements that influence scheduling but do not prevent a task from being scheduled if no node meets the preference.

First, let's inspect the current node to see its labels. Labels are key-value pairs that you can attach to nodes to provide metadata.

docker node inspect self --format '{{ .Spec.Labels }}'

This command inspects the current node (identified by self) and formats the output to show its labels. By default, there might not be any custom labels.

Let's add a label to the current node. We will add a label node_type=app.

docker node update --label-add node_type=app self

This command updates the current node and adds the label node_type=app.

Now, let's verify that the label has been added.

docker node inspect self --format '{{ .Spec.Labels }}'

You should see map[node_type:app] in the output, indicating that the label has been successfully added.

Now, let's create a replicated service named my-constrained-service with a placement constraint that requires the node to have the label node_type=app. We will use the nginx image.

docker service create \
  --name my-constrained-service \
  --replicas 1 \
  --constraint 'node.labels.node_type == app' \
  nginx:latest

This command creates a service with a constraint. --constraint 'node.labels.node_type == app' specifies that tasks for this service can only be scheduled on nodes where the label node_type is equal to app. Since we added this label to the current node, the task should be scheduled here.

Check the service status and tasks:

docker service ls
docker service ps my-constrained-service

You should see my-constrained-service listed and its task running on the current node.

Now, let's create another service with a placement preference. Placement preferences are used to guide the scheduler but are not strictly enforced. We will use the busybox image and prefer nodes with the label node_type=database. Since our current node does not have this label, the task will still be scheduled on the current node, but if there were other nodes with that label, the scheduler would prefer them.

First, pull the busybox image.

docker pull busybox:latest

Now, create the service with a placement preference.

docker service create \
  --name my-preferred-service \
  --replicas 1 \
  --placement-pref 'spread=node.labels.node_type' \
  busybox:latest sleep infinity

The --placement-pref 'spread=node.labels.node_type' option tells the scheduler to spread the tasks across nodes based on the value of the node_type label. In a multi-node swarm with different node_type labels, this would distribute tasks more evenly. In this single-node environment, the task will simply be scheduled on the available node.

Check the service status and tasks:

docker service ls
docker service ps my-preferred-service

You should see my-preferred-service listed and its task running on the current node.

Summary

In this lab, we learned how to use the docker service create command to deploy and manage services in Docker Swarm. We began by creating a simple replicated service using the nginx image, specifying the desired number of replicas for high availability and scalability. We then used docker service ls and docker service ps to verify the service's status and inspect its running tasks.

Subsequently, we explored the creation of a global service, understanding its behavior of running one task on every eligible node in the swarm. This demonstrated the flexibility of Docker Swarm in deploying services based on different requirements.