# 2. Services

### About services <a href="#about-services" id="about-services"></a>

**In a distributed application, different pieces of the app are called “services”**.

**Containers in production**

**A service only runs one image**, but it codifies the way that image runs—what ports it should use, how many replicas of the container should run so the service has the capacity it needs, and so on.

**Scaling a service changes the number of container instances running that piece of software**, assigning more computing resources to the service in the process.

The true implementation of a container in production is running it as a service.

Services codify a container’s behavior in a Compose file, and this file can be used to scale, limit, and redeploy our app. Changes to the service can be applied in place, as it runs, using the same command that launched the service: `docker stack deploy`

Easy to define, run, and scale services with the Docker platform: write a `docker-compose.yml`

## `docker-compose.yml` file

**YAML** file that **defines how Docker containers should behave in production**.

#### `docker-compose.yml` <a href="#docker-composeyml" id="docker-composeyml"></a>

Example:

{% code title="docker-compose.yml" %}

```
version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:
```

{% endcode %}

This `docker-compose.yml` file tells Docker to do the following:

* Pull the image from the registry.
* Run 5 instances of that image as a service called `web`, limiting each one to use, at most, 10% of a single core of CPU time, and 50MB of RAM.
* Immediately restart containers if one fails.
* Map port 4000 on the host to `web`’s port 80.
* Instruct `web`’s containers to share port 80 via a load-balanced network called `webnet`. (Internally, the containers themselves publish to `web`’s port 80 at an ephemeral port.)
* Define the `webnet` network with the default settings (which is a load-balanced overlay network).

## Run your new load-balanced app

Before we can use the `docker stack deploy` command we first run:

```
docker swarm init
```

> **Note**: We get into the meaning of that command in [part 4](https://docs.docker.com/get-started/part4/). If you don’t run `docker swarm init` you get an error that “this node is not a swarm manager.”

Now let’s run it. You need to give your app a name. Here, it is set to `getstartedlab`:

```
docker stack deploy -c docker-compose.yml getstartedlab
```

Our single service stack is running 5 container instances of our deployed image on one host. Let’s investigate.

#### Get the service ID for the one service in our application:

```
docker service ls
```

Look for output for the `web` service, prepended with your app name. If you named it the same as shown in this example, the name is `getstartedlab_web`. The service ID is listed as well, along with the number of replicas, image name, and exposed ports.

Alternatively, you can run `docker stack services`, followed by the name of your stack.

Example: view all services associated with the`getstartedlab` stack:

```
docker stack services getstartedlab
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
bqpve1djnk0x        getstartedlab_web   replicated          5/5                 username/repo:tag   *:4000->80/tcp
```

#### **Tasks**

**A single container running in a service.**

Have **unique IDs that numerically increment, up to the number of `replicas`** you defined in`docker-compose.yml`.

#### List the tasks for your service:

```
docker service ps getstartedlab_web
```

Tasks also show up if you just list all the containers on your system, though that is not filtered by service:

```
docker container ls -q
```

Run `curl -4 http://localhost:4000` several times in a row, or go to that URL in your browser and hit refresh a few times.

![Hello World in browser](https://docs.docker.com/get-started/images/app80-in-browser.png)

Either way, the container ID changes, demonstrating the **load-balancing.**

#### **Load-balancing**

With each request, one of the 5 tasks is chosen, in a round-robin fashion, to respond. The container IDs match your output from the previous command (`docker container ls -q`).

View all tasks of a stack: run **`docker stack ps`** followed by your app name::

```
docker stack ps getstartedlab
ID                  NAME                  IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
uwiaw67sc0eh        getstartedlab_web.1   username/repo:tag   docker-desktop      Running             Running 9 minutes ago                       
sk50xbhmcae7        getstartedlab_web.2   username/repo:tag   docker-desktop      Running             Running 9 minutes ago                       
c4uuw5i6h02j        getstartedlab_web.3   username/repo:tag   docker-desktop      Running             Running 9 minutes ago                       
0dyb70ixu25s        getstartedlab_web.4   username/repo:tag   docker-desktop      Running             Running 9 minutes ago                       
aocrb88ap8b0        getstartedlab_web.5   username/repo:tag   docker-desktop      Running             Running 9 minutes ago
```

> Slow response times?
>
> Depending on your environment’s networking configuration, it may take up to 30 seconds for the containers to respond to HTTP requests. This is not indicative of Docker or swarm performance, but rather an unmet Redis dependency that we address later in the tutorial. For now, the visitor counter isn’t working for the same reason; we haven’t yet added a service to persist data.

## Scale the app

**Change the `replicas` value in `docker-compose.yml`**&#x52;e-run `docker stack deploy` :

```
docker stack deploy -c docker-compose.yml getstartedlab
```

Docker performs an in-place update, **no need to tear the stack down first or kill any containers**.

Now, re-run `docker container ls -q` to see the deployed instances reconfigured. If you scaled up the replicas, more tasks, and hence, more containers, are started.

#### Take down the app and the swarm <a href="#take-down-the-app-and-the-swarm" id="take-down-the-app-and-the-swarm"></a>

* Take the app down with `docker stack rm`:

  ```
  docker stack rm getstartedlab
  ```
* Take down the swarm.

  ```
  docker swarm leave --force
  ```

It’s as easy as that to stand up and scale your app with Docker.

> **Note**: Compose files like this are used to define applications with Docker, and can be uploaded to cloud providers using [Docker Cloud](https://docs.docker.com/docker-cloud/), or on any hardware or cloud provider you choose with [Docker Enterprise Edition](https://www.docker.com/enterprise-edition).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ricardomol.gitbook.io/notes/devops/docker/services.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
