Skip to content

Files

Latest commit

3ac63cb · Dec 27, 2021

History

History
2432 lines (1656 loc) · 90.3 KB

File metadata and controls

2432 lines (1656 loc) · 90.3 KB

十六、附录

1。运行我的第一个 Docker 容器

活动 1.01:从 Docker Hub 中提取并运行 PostgreSQL 容器映像

解决方案:

  1. To start the Postgres Docker container, first determine what environment variables are required to set the default username and password credentials for the database. Reading through the official Docker Hub page, you can see that you have configuration options for the POSTGRES_USER and POSTGRES_PASSWORD environment variables. Pass the environment variables using the -e flag. The final command to start our Postgres Docker container will be as follows:

    docker run -itd -e "POSTGRES_USER=panoramic" -e "POSTGRES_PASSWORD=trekking" postgres:12
    

    运行此命令将启动容器。

  2. Execute the docker ps command to verify that it is running and healthy:

    $ docker ps
    

    该命令应该返回如下输出:

    CONTAINER ID  IMAGE         COMMAND                 CREATED
      STATUS              PORTS               NAMES
    29f115af8cdd  postgres:12   "docker-entrypoint.s…"  4 seconds ago
      Up 2 seconds        5432/tcp            blissful_kapitsa
    

    从前面的输出可以看出,ID 为29f115af8cdd的容器已经启动并运行。

在本练习中,您已经成功启动了一个 PostgreSQL 版本 12 容器,它是全景徒步应用的一部分,将在本书的过程中构建。

活动 1.02:访问全景徒步应用数据库

解决方案:

  1. Log in to the database instance using docker exec to start the PSQL shell inside the container, passing in the --username flag and leaving the --password flag empty:

    $ docker exec -it <containerID> psql --username panoramic --password
    

    这应该会提示您输入密码,并启动一个 PSQL shell。

  2. Use the \l command to list all the databases:

    psql (12.2 (Debian 12.2-2.pgdg100+1))
    Type "help" for help.
    panoramic=# \l
    

    将返回容器中运行的数据库列表:

    Figure 1.4: List of databases

    图 1.4:数据库列表

  3. 最后,使用\q快捷键退出外壳。

  4. 使用docker stopdocker rm命令停止并清理容器实例。

在本活动中,您通过使用在活动 1.01中设置的凭据登录并从 Docker Hub 中提取和运行 PostgreSQL 容器映像来访问容器中运行的数据库。您还列出了容器中运行的数据库。该活动让您亲身体验了如何使用 PSQL shell 访问在任何容器中运行的数据库。

2。Dockerfiles 入门

活动 2.01:在 Docker 容器上运行一个 PHP 应用

解决方案:

  1. 为此活动创建一个名为activity-02-01的新目录:

    mkdir activity-02-01
    
  2. 导航至新创建的activity-02-01目录:

    cd activity-02-01
    
  3. activity-02-01目录下,创建一个名为welcome.php :

    touch welcome.php 
    

    的文件

  4. 现在,使用您最喜欢的文本编辑器打开【T0:

    vim welcome.php 
    
  5. 用活动开始时提供的内容创建welcome.php文件,然后保存并退出welcome.php文件:

    <?php
    $hourOfDay = date('H');
    if($hourOfDay < 12) {
        $message = «Good Morning»;
    } elseif($hourOfDay > 11 && $hourOfDay < 18) {
        $message = «Good Afternoon»;
    } elseif($hourOfDay > 17){
        $message = «Good Evening»;
    }
    echo $message;
    ?>
    
  6. activity-02-01目录下,创建一个名为Dockerfile :

    touch Dockerfile
    

    的文件

  7. 现在,使用您最喜欢的文本编辑器打开【T0:

    vim Dockerfile
    
  8. Add the following content to the Dockerfile, and then save and exit from the Dockerfile:

    # Start with Ubuntu base image
    FROM ubuntu:18.04
    # Set labels
    LABEL maintainer=sathsara
    LABEL version=1.0 
    # Set environment variables
    ENV DEBIAN_FRONTEND=noninteractive
    # Install Apache, PHP, and other packages
    RUN apt-get update && \
        apt-get -y install apache2 \
        php \ 
        curl
    # Copy all php files to the Docker image
    COPY *.php /var/www/html
    # Set working directory
    WORKDIR /var/www/html
    # Create health check
    HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl -f   http://localhost || exit 1
    # Expose Apache
    EXPOSE 80
    # Start Apache
    ENTRYPOINT ["apache2ctl", "-D", "FOREGROUND"]
    

    我们使用ubuntu基础映像开始这个Dockerfile,然后设置几个标签。接下来,DEBIAN_FRONTEND环境变量被设置为noninteractive以使软件包安装非交互。然后安装apache2phpcurl包,将 PHP 文件复制到/var/www/html目录。接下来,配置健康检查并暴露端口80。最后,使用apache2ctl命令启动 Apache 网络服务器。

  9. Now, build the Docker image:

    $ docker image build -t activity-02-01 .
    

    运行build命令后,应该会得到如下输出:

    Figure 2.22: Building the activity-02-01 Docker image

    图 2.22:构建活动-02-01 Docker 映像

  10. Execute the docker container run command to start a new container from the Docker image that you built in the previous step:

```
$ docker container run -p 80:80 --name activity-02-01-container -d activity-02-01
```

由于您是在分离模式下启动 Docker 容器的(带有`-d`标志),前面的命令将输出结果 Docker 容器的 ID。
  1. Now, you should be able to view the Apache home page. Go to the http://127.0.0.1/welcome.php endpoint from your favorite web browser:
![Figure 2.23: PHP application page  ](img/B15021_02_23.jpg)

图 2.23: PHP 应用页面

注意,默认的 Apache 主页是可见的。在前面的输出中,您收到的输出为`Good Morning`。该输出可能会有所不同,根据运行该容器的时间,显示为`Good Afternoon`或`Good Evening`。
  1. 现在,清理容器。首先,用 docker 容器停止命令停止 Docker 容器:
```
$ docker container stop activity-02-01-container
```
  1. 最后,用docker container rm命令
```
$ docker container rm activity-02-01-container
```

移除 Docker 容器

在本练习中,我们学习了如何使用本章中所学的Dockerfile指令来记录一个示例 PHP 应用。我们使用了多个Dockerfile指令,包括FROMLABELENVRUNCOPYWORKDIRHEALTHCHECKEXPOSEENTRYPOINT

3。管理您的 Docker 映像

活动 3.01:使用 Git 哈希版本控制构建脚本

解决方案:

您可以通过多种方式完成本活动。这里有一个例子:

  1. 创建新的构建脚本。第一行显示设置–ex命令,将每一步打印到屏幕上,如果任何一步失败,脚本将失败。第 3 行第 4 行设置注册表和服务名称的变量:

    1 set -ex
    2
    3 REGISTRY=dev.docker.local:5000
    4 SERVICENAME=postgresql
    
  2. 第 6 行中,将GIT_VERSION变量设置为指向您的短 Git 提交散列。构建脚本然后将该值打印到第 7 行 :

    6 GIT_VERSION=`git log -1 --format=%h`
    7 echo "version: $GIT_VERSION "
    

    中的屏幕上

  3. Use the docker build command in line 9 to create your new image and add the docker push command in line 11 to push the image to your local Docker registry:

    9 docker build -t $REGISTRY/$SERVICENAME:$GIT_VERSION .
    10
    11 docker push $REGISTRY/$SERVICENAME:$GIT_VERSION
    

    脚本文件如下所示:

    1 set -ex
    2
    3 REGISTRY=dev.docker.local:5000
    4 SERVICENAME= postgresql
    5
    6 GIT_VERSION=`git log -1 --format=%h`
    7 echo "version: $GIT_VERSION "
    8
    9 docker build -t $REGISTRY/$SERVICENAME:$GIT_VERSION .
    10
    11 docker push $REGISTRY/$SERVICENAME:$GIT_VERSION
    
  4. Run the following command to ensure that the script has been built and runs successfully:

    ./build.sh
    

    您应该得到如下输出:

    ./BuildScript.sh 
    ++ REGISTRY=dev.docker.local:5000
    ++ SERVICENAME=basic-app
    +++ git log -1 --format=%h
    ++ GIT_VERSION=49d3a10
    ++ echo 'version: 49d3a10 '
    version: 49d3a10 
    ++ docker build -t dev.docker.local:5000/basic-app:49d3a10 .
    Sending build context to Docker daemon  3.072kB
    Step 1/1 : FROM postgres
     ---> 873ed24f782e
    Successfully built 873ed24f782e
    Successfully tagged dev.docker.local:5000/basic-app:49d3a10
    ++ docker push dev.docker.local:5000/basic-app:49d3a10
    The push refers to repository [dev.docker.local:5000/basic-app]
    

活动 3.02:配置您的本地 Docker 注册表存储

解决方案:

以下步骤描述了实现活动目标的方法之一:

  1. 在你的主目录中创建test_registry目录:

    mkdir /home/vincesesto/test_registry/
    
  2. 运行本地注册表,但在这种情况下,包括-v选项,该选项将您在上一步中创建的目录连接到/var/lib/registry的容器目录。另外,使用:rw选项确保您可以读写目录:

    docker run -d -p 5000:5000 --restart=always --name registry -v /home/vincesesto/test_registry/registry:/var/lib/registry:rw registry
    
  3. 现在,像平常一样将映像推送到新安装的注册表中:

    docker push dev.docker.local:5000/basic-app:ver1
    
  4. To verify that the images are now being stored in your newly mounted directory, list the files in the registry/docker/registry/v2/repositories/ directory.

    ls  ~/test_registry/registry/docker/registry/v2/repositories/
    

    您应该会看到您在上一步中刚刚推送的新映像:

    basic-app
    

这项活动让我们开始使用一些更高级的 Docker 选项。不要担心,在运行容器时,将有更多的章节专门帮助您理解卷装载和存储。

4。多阶段 Docker 文件

活动 4.01:部署具有多阶段 Docker 构建的 Golang HTTP 服务器

解决方案:

  1. 为此活动创建一个名为activity-04-01的新目录:

    mkdir activity-04-01
    
  2. 导航至新创建的activity-04-01目录:

    cd activity-04-01
    
  3. activity-04-01目录下,创建一个名为main.go :

    $ touch main.go
    

    的文件

  4. 现在,使用您最喜欢的文本编辑器打开main.go文件:

    $ vim main.go
    
  5. 将以下内容添加到main.go文件,然后保存并退出该文件:

    package main
    import (
        "net/http"
        "fmt"
        "log"
        "os"
    )
    func main() {
        http.HandleFunc("/", defaultHandler)
        http.HandleFunc("/contact", contactHandler)
        http.HandleFunc("/login", loginHandler)
        port := os.Getenv("PORT")
        if port == "" {
            port = "8080"
        }
    
        log.Println("Service started on port " + port)
        err := http.ListenAndServe(":"+port, nil)
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
            return
        }
    }
    func defaultHandler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "<h1>Home Page</h1>")
    }
    func contactHandler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "<h1>Contact Us</h1>")
    }
    func loginHandler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "<h1>Login Page</h1>")
    }
    
  6. activity-04-01目录下,创建一个名为Dockerfile的文件。该文件将是多阶段的Dockerfile :

    touch Dockerfile
    
  7. 现在,使用您最喜欢的文本编辑器打开【T0:

    vim Dockerfile
    
  8. Add the following content to the Dockerfile and save the file:

    FROM golang:1.14.2-alpine AS builder
    WORKDIR /myapp
    COPY main.go .
    RUN go build -o main .
    FROM alpine:latest AS runtime
    WORKDIR /myapp
    COPY --from=builder /myapp/main .
    ENTRYPOINT ["./main"]
    EXPOSE 8080
    

    这个Dockerfile有两个阶段,分别叫做builderruntime。构建器阶段使用 Golang Docker 映像作为父映像,并负责从 Golang 源文件创建可执行文件。运行时阶段使用alpine Docker 映像作为父映像,并执行从builder阶段复制的可执行文件。

  9. Now, build the Docker image with the docker build command:

    docker build -t activity-04-01:v1 .
    

    您应该会得到以下输出:

    Figure 4.14: Building the Docker image

    图 4.14:构建 Docker 映像

  10. Use the docker image ls command to list all the Docker images available on your computer. Verify the size of the image:

```
docker images
```

该命令将返回所有可用 Docker 映像的列表:

![Figure 4.15: Listing all Docker images ](img/B15021_04_15.jpg)

图 4.15:列出所有 Docker 映像

在前面的输出中,您可以看到名为`activity-04-01`的优化 Docker 映像的大小为 13.1 MB,而构建器阶段使用的父映像(Golang 映像)的大小为 370 MB。
  1. Execute the docker container run command to start a new container from the Docker image that you built in the previous step:
```
$ docker container run -p 8080:8080 --name activity-04-01-container activity-04-01:v1
```

您应该会得到类似如下的输出:

```
2020/08/30 05:14:10 Service started on port 8080
```
  1. View the application at the following URL in your favorite web browser:
```
http://127.0.0.1:8080/
```

下图显示了我们导航到网址`http://127.0.0.1:8080/`时的主页:

![Figure 4.16: Golang application – Home Page  ](img/B15021_04_16.jpg)

图 4.16: Golang 应用–主页
  1. Now, browse to the following URL on your favorite web browser:
```
http://127.0.0.1:8080/contact
```

下图显示了我们导航到网址`http://127.0.0.1:8080/contact`时的联系人页面:

![Figure 4.17: Golang application – Contact Us page  ](img/B15021_04_17.jpg)

图 4.17: Golang 应用-联系我们页面
  1. Now, enter the following URL in your favorite web browser:
```
http://127.0.0.1:8080/login 
```

下图显示了我们导航到网址`http://127.0.0.1:8080/login`时的登录页面:

![Figure 4.18: Golang application – Login Page  ](img/B15021_04_18.jpg)

图 4.18: Golang 应用–登录页面

在本练习中,我们学习了如何部署一个可以根据调用 URL 返回不同响应的 Golang HTTP 服务器。在本活动中,我们使用多阶段 Docker 构建来创建最小大小的 Docker 映像。

5。用 Docker 编写编写环境

活动 5.01:使用 Docker 编写安装 WordPress

解决方案:

可以通过以下步骤创建数据库并安装 WordPress:

  1. 创建所需的目录,并使用cd命令导航到该目录:

    mkdir wordpress
    cd wordpress
    
  2. 创建一个docker-compose.yaml文件,内容如下:

    version: "3"
    services:
      database:
        image: mysql:5.7
        volumes:
          - data:/var/lib/mysql
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: db
          MYSQL_USER: user
          MYSQL_PASSWORD: password
      wordpress:
        depends_on:
          - database
        image: wordpress:latest
        ports:
          - "8080:80"
        restart: always
        environment:
          WORDPRESS_DB_HOST: database:3306
          WORDPRESS_DB_USER: user
          WORDPRESS_DB_PASSWORD: password
          WORDPRESS_DB_NAME: db
    volumes:
         data: {} 
    
  3. Start the application with the docker-compose up --detach command:

    Figure 5.22: Start of the application

    图 5.22:应用的启动

  4. Check for the running containers with the docker-compose ps command. You should get the following output:

    Figure 5.23: WordPress and database containers

    图 5.23: WordPress 和数据库容器

  5. Open http://localhost:8080 in your browser to check the WordPress setup screen:

    Figure 5.24: WordPress setup screen

图 5.24: WordPress 设置屏幕

在本练习中,您已经使用 Docker Compose 为实际应用创建了一个部署。该应用由一个数据库容器和一个 WordPress 容器组成。两个容器服务都使用环境变量进行配置,通过 Docker Compose 网络和卷进行连接。

活动 5.02:使用 Docker Compose 安装全景徒步应用

解决方案:

可以通过以下步骤创建数据库和全景徒步旅行应用:

  1. 创建所需的目录,并将其更改为:

    mkdir pta-compose
    cd pta-compose
    
  2. 创建一个docker-compose.yaml文件,内容如下:

    version: "3"
    services:
      db:
        image: postgres
        volumes:
          - db_data:/var/lib/postgresql/data/
        environment:
          - POSTGRES_PASSWORD=docker
      web:
        image: packtworkshops/the-docker-workshop:chapter5-pta-web
        volumes:
          - static_data:/service/static
        depends_on:
          - db
      nginx:
        image: packtworkshops/the-docker-workshop:chapter5-pta-nginx
        volumes:
          - static_data:/service/static
        ports:
          - 8000:80
        depends_on:
          - web
    volumes:
      db_data:
      static_data:
    
  3. Start the application with the docker-compose up --detach command. You should get output similar to the following:

    Figure 5.25: Start of the application

    图 5.25:应用的启动

    注意

    也可以使用docker-compose up -d命令启动应用。

  4. Check for the running containers with the docker-compose ps command. You should get output similar to the following:

    Figure 5.26 Application, database, and nginx containers

    图 5.26 应用、数据库和 nginx 容器

  5. Open the administration section of the Panoramic Trekking App in the browser with the address of http://0.0.0.0:8000/admin:

    Figure 5.27: Admin setup logon

    图 5.27:管理员设置登录

    注意

    也可以运行firefox http://0.0.0.0:8000/admin命令,打开全景徒步应用的管理部分。

    使用用户名admin和密码changeme登录,添加新的照片和国家。将出现以下屏幕:

    Figure 5.28: Admin setup view

    图 5.28:管理设置视图

  6. Open the Panoramic Trekking App at the address http://0.0.0.0:8000/photo_viewer in the browser:

    Figure 5.29: Application view

图 5.29:应用视图

在本练习中,您已经使用 Docker Compose 创建了一个三层应用,其中包含 PostgreSQL 数据库、后端和代理服务层。所有服务都使用 Docker Compose 及其网络和存储功能进行配置和连接。

6。Docker 网络简介

活动 6.01: L 更新 Docker 网络驱动程序

解决方案:

以下是根据最佳实践完成本活动的最常见方式:

  1. Use the docker network create command to create a network for the NGINX web server. Call it webservernet and give it a subnet of 192.168.1.0/24 and a gateway of 192.168.1.1:

    $ docker network create webservernet --subnet=192.168.1.0/24 --gateway=192.168.1.1
    

    这应该会创建bridge网络,webservernet

  2. Use the docker run command to create an NGINX web server. Use the -p flag to forward port 8080 on the host to port 80 on the container instance:

    $ docker run -itd -p 8080:80 --name webserver1 --network webservernet nginx:latest
    

    这将启动webservernet网络中的webserver1容器。

  3. Use the docker run command to start an Alpine Linux container named monitor in host networking mode. This way, you will know that the container has access to the host ports of the main system as well as access to the bridge network IP address:

    $ docker run -itd --name monitor --network host alpine:latest
    

    这将在host网络模式下启动一个 Alpine Linux 容器实例。

  4. Use docker inspect to find the IP address of the webserver1 container:

    $ docker inspect webserver1
    

    容器的详细信息将以 JSON 格式显示;从IPAddress参数获取 IP 地址:

    Figure 6.27: Inspecting the webserver1 container instance

    图 6.27:检查 webserver1 容器实例

  5. Access an sh shell inside the monitoring container using the docker exec command:

    $ docker exec -it monitor /bin/sh
    

    这会让你陷入一个根壳。

  6. Use the apk install command to install the curl command inside this container:

    / # apk add curl
    

    这将安装curl实用程序:

    fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main
    /x86_64/APKINDEX.tar.gz
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community
    /x86_64/APKINDEX.tar.gz
    (1/4) Installing ca-certificates (20191127-r1)
    (2/4) Installing nghttp2-libs (1.40.0-r0)
    (3/4) Installing libcurl (7.67.0-r0)
    (4/4) Installing curl (7.67.0-r0)
    Executing busybox-1.31.1-r9.trigger
    Executing ca-certificates-20191127-r1.trigger
    OK: 7 MiB in 18 packages
    
  7. Use the curl command to validate connectivity works at the host level, by calling port 8080 on the host machine:

    / # curl -v http://localhost:8080
    

    您应该会收到来自 NGINX 的200 OK响应,表明在主机级别成功连接:

    Figure 6.28: Accessing the webserver1 container from the exposed ports on the host

    图 6.28:从主机上公开的端口访问 webserver1 容器

  8. Likewise, use the curl command to access the IP address of the container in the Docker bridge network directly over port 80:

    / # curl -v 192.168.1.2:80
    

    同样,您应该会收到另一个200 OK响应,表示连接成功:

    Figure 6.29: Accessing the NGINX web server from the IP  address of the container instance

图 6.29:从容器实例的 IP 地址访问 NGINX 网络服务器

在本练习中,我们能够使用不同的 Docker 网络驱动程序来说明容器之间的连接。这个场景适用于现实世界的生产基础设施,因为当部署一个容器化的解决方案时,工程师将努力部署一个尽可能不可变的基础设施。借助在 Docker 中部署完全模拟主机级网络的容器的能力,可以设计出在主机操作系统上只需极少配置的基础架构。这使得部署和扩展 Docker 所部署的主机变得非常容易。诸如curl和其他监控工具的包可以部署到在 Docker 主机上运行的容器中,而不是安装在主机本身上。这保证了部署和维护的便利性,并提高了部署更多主机以满足不断增长的需求的速度。

活动 6.02:在之上建立网络

解决方案:

  1. 使用docker network create命令,通过传递自定义的subnetgatewayoverlay网络驱动程序:

    $ docker network create panoramic-net --subnet=10.2.0.0/16 --gateway=10.2.0.1 --driver overlay
    

    ,在 Docker 集群的Machine1上创建一个名为panoramic-net的 Dockeroverlay网络

  2. Use the docker service create command on Machine1 to create a service named trekking-app in the panoramic-net network:

    $ docker service create -t --name trekking-app --replicas=1 --network panoramic-net alpine:latest
    

    这将在panoramic-net overlay网络中启动一项名为trekking-app的服务。

  3. 使用Machine1上的docker service create命令在panoramic-net网络中创建名为database-app的服务。设置默认凭证并指定 Docker 映像的postgres:12版本:

    $ docker service create -t --name database-app --replicas=1 --network panoramic-net -e "POSTGRES_USER=panoramic" -e "POSTGRES_PASSWORD=trekking" postgres:12
    
  4. Use docker exec to access an sh shell inside the trekking-app service container:

    $ docker exec -it trekking-app.1.qhpwxol00geedkfa9p6qswmyv /bin/sh
    

    这将把你放到trekking-app容器实例中的一个根外壳中。

  5. Use the ping command to validate network connectivity to the database-app service:

    / # ping database-app
    

    ICMP 回复应表明连接成功:

    PING database-app (10.2.0.5): 56 data bytes
    64 bytes from 10.2.0.5: seq=0 ttl=64 time=0.261 ms
    64 bytes from 10.2.0.5: seq=1 ttl=64 time=0.352 ms
    64 bytes from 10.2.0.5: seq=2 ttl=64 time=0.198 ms
    

在本练习中,我们利用了一个跨 Docker 集群的定制 Docker overlay网络来说明使用 Docker DNS 的两个 Docker 集群服务之间的连接。在现实世界的多层应用中,许多微服务可以部署在大型 Docker 集群中,这些集群使用overlay网络网格直接相互对话。了解overlay网络如何与 Docker DNS 协同工作,对于实现高效的可扩展性至关重要,因为您的容器化基础架构在持续增长。

7。Docker 仓库

活动 7.01:在 PostgreSQL 数据库中存储容器事件(状态)数据

解决方案:

  1. 运行以下命令删除主机中的所有对象:

    $ docker container rm -fv $(docker container ls -aq)
    $docker image rm $(docker image ls -q)
    
  2. 获取卷名,然后使用以下命令删除所有卷:

    $docker volume ls
    $docker volume rm <volume names separated by spaces>
    
  3. 获取网络名称,然后使用以下命令删除所有网络:

    $docker network ls
    $docker network rm <network names separated by spaces>
    
  4. 打开两个终端,一个专用于看到docker events --format '{{json .}}'生效。另一个应该打开以执行前面提到的高级步骤。

  5. In the first terminal, run the following command:

    docker events --format '{{json .}}'.
    

    您应该得到如下输出:

    Figure 7.11: Output of the docker events command

    图 7.11:docker 事件命令的输出

  6. Run the following command to start the ubuntu container in the second terminal:

    $docker run -d ubuntu:14.04
    

    您应该得到如下输出:

    Figure 7.12: Output of the docker run command

    图 7.12:Docker 运行命令的输出

  7. 在第二个终端中使用以下命令创建名为vol1的卷:

    $docker volume create vol1
    
  8. 在第二个终端中使用以下命令创建名为net1的网络:

    $docker network create net1
    
  9. 使用以下命令移除容器:

    $docker container rm -fv <container ID>
    
  10. 使用以下命令删除卷和网络:

```
$docker volume rm vol1
$docker network rm net1
```
  1. docker events终端点击 Ctrl + C 终止。
  2. Check the following two examples to understand the JSON output:
**例 1** :

```
{"status":"create","id":"43903b966123a7c491b50116b40827daa03
da5d350f8fef2a690fc4024547ce2","from":"ubuntu:14.04","Type":
"container","Action":"create","Actor":{"ID":"43903b966123a7c
491b50116b40827daa03da5d350f8fef2a690fc4024547ce2","Attributes":
{"image":"ubuntu:14.04","name":"upbeat_johnson"}},"scope":"local",
"time":1592516703,"timeNano":1592516703507582404}
```

**例 2** :

```
{"Type":"network","Action":"connect","Actor":{"ID":"52855e1561
8e37b7ecc0bb26bc42847af07cae65ddd3b68a029e40006364a9bd",
"Attributes":{"container":"43903b966123a7c491b50116b40827daa03d
a5d350f8fef2a690fc4024547ce2","name":"bridge","type":"bridge"}},
"scope":"local","time":1592516703,"timeNano":1592516703911851347}
```

你会发现不同的对象有不同的属性和结构。
  1. 运行带有卷的 PostgreSQL 容器。命名容器db1 :
```
$docker container run --name db1 -v db:/var/lib/postgresql/data -e POSTGRES_PASSWORD=password -d postgres
```
  1. 运行exec命令,以便用要执行的命令替换 bash。外壳将变为posgres=#表示您在容器内:
```
$ docker container exec -it db1 psql -U postgres
```
  1. 创建一个包含两列的表格:serial类型的IDjson类型的info:
```
CREATE TABLE events (ID serial NOT NULL PRIMARY KEY, info json NOT NULL);
```
  1. 将第一个例子输出的第一行JSON插入表格:
```
INSERT INTO events (info) VALUES ('{"status":"create","id":"43903b966123a7c491b50116b40827daa03da 5d350f8fef2a690fc4024547ce2","from":"ubuntu:14.04","Type":"container","Action":"create","Actor":{"ID":"43903b966123a7c49 1b50116b40827daa03da5d350f8fef2a690fc4024547ce2","Attributes":{"image":"ubuntu:14.04","name":"upbeat_johnson"}},"scope":"local","time":1592516703,"timeNano":1592516703507582404}');
```
  1. Verify that the row is saved in the database by typing the following SQL statement:
```
select * from events;
```

您应该得到如下输出:

![Figure 7.13: Verifying that the row is saved in the database ](img/B15021_07_13.jpg)

图 7.13:验证该行是否保存在数据库中
  1. Insert Docker events into the events table using the SQL insert command.
注意

请参考位于[https://packt.live/2ZKfGgB](https://packt.live/2ZKfGgB)的`events.txt`文件,使用`insert`命令插入 Docker 事件。

您应该得到如下输出:

![Figure 7.14: Inserting multiple rows in the database  ](img/B15021_07_14.jpg)

图 7.14:在数据库中插入多行

从这个输出中,很明显有 11 个事件被成功地插入到 PostgreSQL 数据库中。
  1. Run the following three queries one by one.
**查询 1** :

```
SELECT * FROM events WHERE info ->> 'status' = 'pull';
```

输出如下所示:

![Figure 7.15: Output of Query 1 ](img/B15021_07_08.jpg)

图 7.15:查询 1 的输出

查询 2 :

SELECT * FROM events WHERE info ->> 'status' = 'destroy';

输出如下所示:

Figure 7.16: Output of Query 2

图 7.16:查询 2 的输出

查询 3 :

SELECT info ->> 'id' as id FROM events WHERE info ->> 'status'=     'destroy';

输出如下所示:

Figure 7.17: Output of Query 3

图 7.17:查询 3 的输出

在本练习中,您学习了如何记录和监视容器,如何使用 SQL 语句查询容器的事件,以及如何获取事件的 JSON 输出并保存在 PostgreSQL 数据库中。您还学习了 JSON 输出结构,并学习了如何查询它。

活动 7.02:与主机共享 NGINX 日志文件

解决方案:

  1. Verify that you do not have the /var/mylogs folder on your host by running the following command:

    $cd /var/mylogs
    

    您应该得到如下输出:

    Bash: cd: /var/mylogs: No such file or directory
    
  2. Run a container based on the NGINX image. Specify the path of the shared volumes on the host and inside the container in the run command. Inside the container, NGINX uses the /var/log/nginx path for the log files. Specify the path on the host as /var/mylogs:

    $docker container run -d -v /var/mylogs:/var/log/nginx nginx
    

    如果本地没有映像,Docker 引擎将自动提取映像:

    Figure 7.18: Output of the docker run command

    图 7.18:Docker 运行命令的输出

  3. Go to the path of /var/mylogs. List all the files in that directory:

    $cd /var/mylogs
    $ls
    

    你应该在那里找到两个文件:

    access.log         error.log
    
  4. (Optional) If no errors were generated, the two files will be empty. You check the contents by using the cat Linux command or by using the tail Linux command. As we used the cat command before, let's use the tail command for this example:

    $tail -f *.log
    

    您应该得到如下输出:

    ==>  access.log  <==
    ==>  error.log   <==
    

    由于该 NGINX 服务器未产生任何错误或未被访问,文件当前为空。但是,如果 NGINX 在任何时刻崩溃,产生的错误将保存在error.log中。

在本练习中,您学习了如何将容器的日志文件共享给主机。您使用的是 NGINX 服务器,所以如果它崩溃了,您可以从它的日志文件中追踪发生了什么。

8。服务发现

活动 8.01:利用詹金斯和索纳库

解决方案:

  1. Install SonarQube and run it as a container using the following command:

    docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube
    

    您应该获得容器标识作为输出:

    4346a99b506b1bec8000e429471dabac57e3f565b154ee921284ec685497bfae
    
  2. Log in to SonarQube by using admin/admin credentials:

    Figure 8.38: Log in to SonarQube

    图 8.38:登录到 SonarQube

    成功登录后,将出现类似以下内容的屏幕:

    Figure 8.39: The SonarQube dashboard

    图 8.39:SonarQube 仪表板

  3. 在右上角,单击用户。将出现一个下拉菜单。点击My Account:

  4. Scroll down and click on Generate under Security to generate a token. You must copy it now because you will not be able to access it later:

    Figure 8.40: Generating the token

    图 8.40:生成令牌

  5. In Jenkins, click on Manage Jenkins > Plugin Manager. Search for Sonar in the Available list. Install the SonarQube Scanner plugin.

    Figure 8.41: Installing the SonarQube Scanner plugin

    图 8.41:安装 SonarQube 扫描仪插件

  6. Verify that the installation is correct by clicking on the hit_count project and then clicking the Configure option. Click on Add build step and then Execute SonarQube Scanner on the Build tab, as in Figure 8.43:

    Figure 8.42: Selecting Execute SonarQube Scanner

    图 8.42:选择执行声纳立方体扫描仪

  7. However, the new box will generate errors, like the one shown in the following screenshot. To rectify that, integrate SonarQube and Jenkins through the system configuration and global tool configuration options:

    Figure 8.43: Errors generated since SonarQube is not configured yet

    图 8.43:由于尚未配置 SonarQube 而产生的错误

  8. In Jenkins, click on Manage Jenkins. Click the Global Tool Configuration option and then click Add SonarQube Scanner:

    Figure 8.44: Adding SonarQube Scanner on the Global Tool Configuration page

    图 8.44:在全局工具配置页面上添加 SonarQube 扫描仪

  9. Enter the name SonarQube Scanner. Check Install automatically. Under Install from Maven Central, in Version, select SonarQube Scanner 3.2.0.1227. Click on Add Installer. In the Label field, enter SonarQube. In the Download URL for binary archive field, enter the link https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-3.2.0.1227-linux.zip.

    点击Save

    Figure 8.45: Adding details for SonarQube Scanner

    图 8.45:添加 SonarQube 扫描仪的详细信息

    您现在已经完成了Global Tool Configuration选项,所以是时候转到Configure System选项了。

  10. In Manage Jenkins, click Configure System:

![Figure 8.46: Click on Configure System on the Manage Jenkins page ](img/B15021_08_46.jpg)

图 8.46:单击管理詹金斯页面上的配置系统
  1. You cannot enter the system configuration right now as it asks for Server Authentication Token. When you click the Add button, it will do nothing. Enter the token as secret text in the following steps, and then return to Manage Jenkins:
![Figure 8.47: Inserting the SonarQube token in Jenkins configuration ](img/B15021_08_47.jpg)

图 8.47:在 Jenkins 配置中插入 SonarQube 令牌
  1. Click on Manage Credentials:
![Figure 8.48: The Manage Jenkins page ](img/B15021_08_48.jpg)

图 8.48:管理詹金斯页面
  1. Click on Jenkins:
![Figure 8.49: The Jenkins Credentials page ](img/B15021_08_49.jpg)

图 8.49:詹金斯证书页面
  1. Click on Global credentials (unrestricted):
![Figure 8.50: The Global credentials (unrestricted) domain ](img/B15021_08_50.jpg)

图 8.50:全局凭证(无限制)域
  1. Click on adding some credentials:
![Figure 8.51: Adding some credentials  ](img/B15021_08_51.jpg)

图 8.51:添加一些凭证
  1. In the Kind drop-down menu, click on Secret text:
![Figure 8.52: Selecting Secret text for Kind  ](img/B15021_08_52.jpg)

图 8.52:为“种类”选择机密文本
  1. In the Secret textbox, paste the token that you copied in Step 5 in this activity. In the ID field, enter SonarQubeToken. Click OK:
![Figure 8.53: Adding the token to the Secret textbox  ](img/B15021_08_53.jpg)

图 8.53:将令牌添加到机密文本框

`SonarQubeToken`将保存在`Global credentials`选项中。您将看到类似于以下内容的屏幕:

![Figure 8.54: SonarQubeToken saved in the Global credentials ](img/B15021_08_54.jpg)

图 8.54:保存在全局凭证中的 SonarQubeToken
  1. Return to Manage Jenkins. Click Configuration System and then Refresh. Now, in the Server Authentication Token drop-down menu, you will find SonarQubeToken. Check Enable injection of SonarQube server configuration as build environment variables. Enter SonarQube in the Name field. Enter http://<your IP>:9000 in the Server URL field. Then click Save:
您可以运行`ifconfig`命令获取您的 IP。您将在输出的`en0`部分找到该 IP:

```
$ ifconfig
```

这是将 Jenkins 与 SonarQube 集成的最后一步。让我们回到项目上来。
  1. Build Environment中,勾选Prepare SonarQube Scanner environment。将Server authentication token设置为SonarQubeToken:
  2. Now, click on the project name and then Configure. In the Build step, enter the following code in the Analysis Properties field:
```
sonar.projectKey=hit_count
sonar.projectName=hit_count
sonar.projectVersion=1.0
sonar.sources=.
sonar.language=py
sonar.sourceEncoding=UTF-8
# Test Results
sonar.python.xunit.reportPath=nosetests.xml
# Coverage
sonar.python.coverage.reportPath=coverage.xml
# Linter (https://docs.sonarqube.org/display/PLUG/Pylint+Report)
#sonar.python.pylint=/usr/local/bin/pylint
#sonar.python.pylint_config=.pylintrc
#sonar.python.pylint.reportPath=pylint-report.txt
```

点击`Save`。
  1. After saving, you will find the SonarQube logo showing on the project page, as in Figure 8.55. Click on Build Now:
![Figure 8.55: The SonarQube option showing on our project's dashboard ](img/B15021_08_55.jpg)

图 8.55:显示在我们项目仪表板上的 SonarQube 选项
  1. In Build History, click on Console Output. You should get the screen similar to the following:
![Figure 8.56: Console Output ](img/B15021_08_56.jpg)

图 8.56:控制台输出
  1. 查看SonarQube上的报告。在浏览器中,键入http://<ip>:9000http://localhost:9000。你会发现詹金斯自动将你的hit_count项目添加到了索纳库:
  2. 点击hit_count。你会发现一份详细的报告。每当 Jenkins 构建项目时,SonarQube 都会自动分析代码

在本练习中,您学习了如何将 Jenkins 与 SonarQube 集成并安装所需的插件,您通过在浏览器中检查 SonarQube 验证了这一点。您还将 SonarQube 应用于您的简单网络应用hit_counter

活动 8.02:在全景徒步旅行应用中利用詹金斯和索纳库

解决方案:

  1. 在詹金斯中创建一个名为trekking的新项目。选择它作为FREESTYLE项目。点击OK

  2. General选项卡中,选择Discard old builds

  3. In the Source Code Management tab, select GIT. Then enter the URL http://github.com/efoda/trekking_app:

    Figure 8.57: Inserting the GitHub URL

    图 8.57:插入 GitHub 网址

  4. In Build Triggers, select Poll SCM and enter H/15 * * * *:

    Figure 8.58: Inserting the scheduling code

    图 8.58:插入调度代码

  5. In the Build Environment tab, select Prepare SonarQube Scanner environment. Select the Server authentication token from the drop-down menu:

    Figure 8.59: Selecting SonarQubeToken as the Server authentication token

    图 8.59:选择 SonarQubeToken 作为服务器认证令牌

  6. In the Build tab, enter the following code in Analysis properties:

    sonar.projectKey=trekking
    sonar.projectName=trekking
    sonar.projectVersion=1.0
    sonar.sources=.
    sonar.language=py
    sonar.sourceEncoding=UTF-8
    # Test Results
    sonar.python.xunit.reportPath=nosetests.xml
    # Coverage
    sonar.python.coverage.reportPath=coverage.xml
    # Linter (https://docs.sonarqube.org/display/PLUG/Pylint+Report)
    #sonar.python.pylint=/usr/local/bin/pylint
    #sonar.python.pylint_config=.pylintrc
    #sonar.python.pylint.reportPath=pylint-report.txt
    

    点击Save

  7. Select Build Now. When the build is done successfully, select Console Output. The following output will indicate that it finished successfully:

    Figure 8.60: Verifying Jenkins has built the image successfully

    图 8.60:验证 Jenkins 是否成功构建了映像

  8. Switch to the SonarQube tab in the browser and check the output. The following report indicates that the trekking app has two bugs and zero security vulnerabilities:

    Figure 8.61: Report shown in the SonarQube browser tab

    图 8.61:显示在 SonarQube 浏览器选项卡中的报告

    如果您点击New Code,它将是空白的,因为您只构建了一次项目。当詹金斯另一次构建它时,你会发现两个构建之间的比较。

  9. 如果你想编辑项目的代码,把 GitHub 代码转移到你的账户上,然后编辑代码来修复错误和漏洞。编辑项目的配置,使您的 GitHub 代码代替Source Code选项卡中提供的代码。

在本练习中,您将 Jenkins 与 SonarQube 集成在一起,并将其应用于全景徒步旅行应用。在活动结束时,您检查了 SonarQube 生成的报告,这些报告显示了代码中的错误和漏洞。

9。DockerSwarm

活动 9.01:将全景徒步应用部署到单节点 DockerSwarm

解决方案:

您可以通过多种方式来执行此活动。这些步骤是一种方法:

  1. 为应用创建一个目录。在这种情况下,您将创建一个名为Activity1的目录,并使用cd命令进入新目录:

    mkdir Activity1; cd Activity1
    
  2. 从其 GitHub 存储库中克隆应用,以确保您将拥有想要部署到群中的全景徒步应用服务所需的所有相关信息和应用:

    git clone https://github.com/vincesesto/trekking_app.git
    
  3. You won't need any of the supporting directories for NGINX, but ensure that your web service and database running are listed here, including the panoramic_trekking_app and photo_viewer directories and the Dockerfile, entrypoint.sh, manage.py, and requirements.txt scripts and files:

    ls -l
    

    该命令应返回类似如下的输出:

    -rw-r--r--   1 vinces  staff   533 12 Mar 15:02 Dockerfile
    -rwxr-xr-x   1 vinces  staff  1077 12 Mar 15:02 entrypoint.sh
    -rwxr-xr-x   1 vinces  staff   642 12 Mar 15:02 manage.py
    drwxr-xr-x   9 vinces  staff   288 12 Mar 15:02 
    panoramic_trekking_app
    drwxr-xr-x  12 vinces  staff   384 12 Mar 15:02 photo_viewer
    -rw-r--r--   1 vinces  staff   105 12 Mar 15:02 requirements.txt
    
  4. 在目录中创建.env.dev文件,并添加以下详细信息以供panoramic_trekking_app在其settings.py文件中使用。这些环境变量将设置数据库名称、用户、密码和其他数据库设置:

    SQL_ENGINE=django.db.backends.postgresql
    SQL_DATABASE=pta_database
    SQL_USER=pta_user
    SQL_PASSWORD=pta_password
    SQL_HOST=db
    SQL_PORT=5432
    PGPASSWORD=docker
    
  5. Create a new docker-compose.yml file and open it with your text editor and add in the following details:

    version: '3.3'
    services:
      web:
        build: .
     image: activity_web:latest
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
          - static_volume:/service/static
        ports:
          - 8000:8000
        environment:
          - PGPASSWORD=docker
        env_file:
          - ./.env.dev
        depends_on:
          - db
      db:
        image: postgres
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        environment:
          - POSTGRES_PASSWORD=docker
        ports:
          - 5432:5432
    volumes:
      postgres_data:
      static_volume:
    

    docker-compose.yml文件中突出显示的行可以看出,web服务依赖于activity_web:latest Docker 映像。

  6. 运行以下docker build命令构建映像并适当标记:

    docker build -t activity_web:latest .
    
  7. It's now time to deploy the stack to Swarm. Run the following stack deploy command using the docker-compose.yml file you have created:

    docker stack deploy --compose-file docker-compose.yml activity_swarm
    

    一旦创建了网络,您应该会看到activity_swarm_webactivity_swarm_db服务可用:

    Creating network activity_swarm_default
    Creating service activity_swarm_web
    Creating service activity_swarm_db
    
  8. Run the service ls command:

    docker service ls
    

    验证所有服务已成功启动并显示1/1副本,如我们这里所示:

    ID       NAME                MODE         REPLICAS
      IMAGE
    k6kh…    activity_swarm_db   replicated   1/1
      postgres:latest
    copa…    activity_swarm_web  replicated   1/1
      activity_web:latest  
    
  9. 最后,打开你的网络浏览器,确认你可以从http://localhost:8000/admin/http://localhost:8000/photo_viewer/访问网站。

全景徒步旅行应用的创建和设置方式类似于您在本章中已经完成的其他一些服务。

活动 9.02:在群运行时执行应用更新

解决方案:

我们可以通过多种方式进行这项活动。以下步骤详细介绍了一种方法:

  1. If you do not have a Swarm running, deploy the docker-compose.yml file you created in Activity 9.01, Deploying the Panoramic Trekking App to a Single-Node Docker Swarm:

    docker stack deploy --compose-file docker-compose.yml activity_swarm
    

    如您所见,这三项服务现在都在运行:

    Creating network activity_swarm_default
    Creating service activity_swarm_web
    Creating service activity_swarm_db
    
  2. In the same directory where you have performed the stack deploy command, open the photo_viewer/templates/photo_index.html file with your text editor and change line four to match the following details, basically adding the word Patch to the main heading:

    photo_index.html

    1 {% extends "base.html" %}
    2 {% load static %}
    3 {% block page_content %}
    4 <h1>Patch Panoramic Trekking App - Photo Viewer</h1>
    

    你可以在这里找到完整的代码https://packt.live/3ceYnta

  3. 构建一个新的映像,这次使用以下命令将映像标记为【T0:

    docker build -t activity_web:patch_1 .
    
  4. Deploy the patch to your Swarm web service using the service update command. Provide the image name and the service the update is going to be applied to as well:

    docker service update --image activity_web:patch_1 activity_swarm_web
    

    输出应该如下所示:

    …
    activity_swarm_web
    overall progress: 1 out of 1 tasks 
    1/1: running   [=======================================>] 
    verify: Service converged
    
  5. List the services running and verify that the new image is running as part of the activity_swarm_web service:

    docker service ls
    

    从输出中可以看到,web 服务不再用latest标记。它现在显示patch_1映像标签:

    ID         NAME                  MODE          REPLICAS
      IMAGE
    k6kh…      activity_swarm_db     replicated    1/1
      postgres:latest
    cu5p…      activity_swarm_web    replicated    1/1
      activity_web:patch_1
    
  6. Verify that the changes have been applied to the image by accessing http://localhost:8000/photo_viewer/ and seeing that the heading now shows Patch Panoramic Trekking App:

    Figure 9.10: Patch version of the Panoramic Trekking App

图 9.10:全景徒步应用的补丁版本

在本活动中,您对全景徒步旅行应用进行了微小的更改,以便对服务进行滚动更新。然后,您将映像部署到运行环境中,并执行滚动更新以验证更改是否成功。标题中的更改表明滚动更新已成功执行。

10。KubernetesKubernetesKubernetesKubernetesKubernetesKubernetesKubernetesKubernetesKubernetesKubernetes

活动 10.01:在 Kubernetes 上安装全景徒步应用

解决方案:

可以通过以下步骤创建数据库和全景徒步旅行应用:

  1. Install the database with the following helm command:

    helm install database stable/postgresql --set postgresqlPassword=kubernetes
    

    这将为 PostgreSQL 安装多个 Kubernetes 资源,并显示如下摘要:

    Figure 10.23: Database installation

    图 10.23:数据库安装

    该输出首先列出与 Helm 图表相关的信息,如名称、部署时间、状态和版本,然后是与 PostgreSQL 实例相关的信息以及如何访问它。在 Helm 图表中,这是一种广泛接受的方法,用于在安装图表后提供此类信息。否则,将很难学习如何连接到 Helm 安装的应用。

  2. Create a statefulset.yaml file with the following content:

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: panoramic-trekking-app
    spec:
      serviceName: panoramic-trekking-app
      replicas: 1
      selector:
        matchLabels:
          app: panoramic-trekking-app
      template:
        metadata:
          labels:
            app: panoramic-trekking-app
        spec:
          containers:
          - name: nginx
            image: packtworkshops/the-docker-workshop:          chapter10-pta-nginx
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: static
              mountPath: /service/static
          - name: pta
            image: packtworkshops/the-docker-workshop:          chapter10-pta-web
            volumeMounts:
            - name: static
              mountPath: /service/static
      volumeClaimTemplates:
      - metadata:
          name: static
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 1Gi
    

    该文件创建一个名为panoramic-trekking-app的状态集。在spec部分定义了两个容器,名称分别为nginxpta。此外,体积索赔以名称static定义,并安装在两个容器上。

  3. Deploy the panoramic-trekking-app StatefulSet with the following command:

    kubectl apply -f statefulset.yaml
    

    这将为我们的应用创建一个状态集:

    StatefulSet.apps/panoramic-trekking-app created
    
  4. Create a service.yaml file with the following content:

    apiVersion: v1
    kind: Service
    metadata:
      name: panoramic-trekking-app
      labels:
        app: panoramic-trekking-app
    spec:
      ports:
      - port: 80
        name: web
      type: LoadBalancer
      selector:
        app: panoramic-trekking-app
    

    该服务定义有一个LoadBalancer类型来访问带有标签app: panoramic-trekking-app的容器。港口80将可以进入吊舱的web港口。

  5. Deploy the panoramic-trekking-app Service with the following command:

    kubectl apply -f service.yaml
    

    这将创建如下服务资源:

    Service/panoramic-trekking-app created
    
  6. Get the IP of the Service with the following command:

    minikube service panoramic-trekking-app --url
    http://192.168.64.14:32009
    

    按照以下步骤存储 IP 以访问全景徒步应用。

  7. Open the administration section of the Panoramic Trekking App in the browser with http://$SERVICE_IP/admin:

    Figure 10.24: Admin login view

    图 10.24:管理员登录视图

  8. Log in with the username admin and the password changeme and add new photos and countries:

    Figure 10.25: Admin setup view

    图 10.25:管理设置视图

  9. Open the Panoramic Trekking App at http://$SERVICE_IP/photo_viewer in the browser:

    Figure 10.26: Application view

图 10.26:应用视图

照片查看器应用显示照片和国家已从数据库中检索。它还表明应用设置正确,运行正常。

在本练习中,您已经将全景徒步旅行应用部署到了 Kubernetes 集群。您从使用 Helm 图表的数据库开始,然后为应用创建 Kubernetes 资源。最后,您从浏览器访问了该应用,并通过添加新照片对其进行了测试。在本练习结束时,您已经发现了如何使用正式的 Helm 图表来部署数据库,创建了一系列 Kubernetes 资源来连接数据库和部署应用,并从集群中收集信息来访问应用。活动中的步骤涵盖了部署在 Kubernetes 集群中的容器化应用的生命周期。

11 时。Docker 保安

活动 11.01:为全景徒步旅行应用设置 seccomp 配置文件

解决方案:

您可以通过多种方式创建seccomp配置文件,阻止用户执行mkdirkilluname命令。这些步骤展示了实现这一点的一种方法:

  1. 如果本地还没有postgres映像,执行以下命令:

    docker pull postgres
    
  2. 使用系统上的wget命令获取默认seccomp配置文件的副本。将您正在下载的文件命名为activity1.json :

    wget https://raw.githubusercontent.com/docker/docker/v1.12.3/profiles/seccomp/default.json - O activity1.json
    
  3. Remove the following three commands from the profile to allow us to further lock down our image. Open the activity1.json file with your favorite text editor and remove the following lines from the file. You should look to remove lines 1500 to 1504 to remove the uname command, 669 to 673 to remove the mkdir command, and lines 579 to 583 to remove the kill command from being available:

    1500                 {
    1501                         "name": "uname",
    1502                         "action": "SCMP_ACT_ALLOW",
    1503                         "args": []
    1504                 },
    
    669                 {
    670                         "name": "mkdir",
    671                         "action": "SCMP_ACT_ALLOW",
    672                         "args": []
    673                 },
    
    579                 {
    580                         "name": "kill",
    581                         "action": "SCMP_ACT_ALLOW",
    582                         "args": []
    583                 },
    

    您可以在以下链接找到修改后的activity1.json文件:https://packt.live/32BI3PK

  4. 使用postgres映像测试新配置文件,方法是在运行时分配一个新配置文件,在运行映像时使用–-security-opt seccomp=activity1.json选项:

    docker run --rm -it --security-opt seccomp=activity1.json postgres sh
    
  5. As you are now logged on to the running container, test the new permissions of the profile you have now assigned to the container. Perform a mkdir command to create a new directory on the system:

    ~ $ mkdir test
    

    该命令应显示一个Operation not permitted输出:

    mkdir: can't create directory 'test': Operation not permitted
    
  6. To test that you are no longer able to kill the running processes, you need to start something up. Start the top process and run it in the background. Do this by typing top into the command line and then adding &, before pressing Enter to run the process in the background. The following command then provides the process command (ps) to see what processes are running on the container:

    ~ $ top & ps
    

    从下面的输出可以看出,top进程运行为PID 8:

    PID   USER         TIME    COMMAND
     1    20002        0:00    sh
     8    20002        0:00    top
    10    20002        0:00    ps
    [1]+  Stopped  (tty output)       top
    

    注意

    基于postgres映像的容器中没有pstop命令。但是,这不会导致任何问题,因为运行带有任何随机 pid 号的kill命令就足以证明不允许运行该命令。

  7. Kill the top process by using the kill -9 command followed by the PID number of the process you want to kill. The kill -9 command will try to force the command to stop:

    ~ $ kill -9 8
    

    你应该看到Operation not permitted:

    sh: can't kill pid 8: Operation not permitted
    
  8. Test the uname command. This is a little different from the other commands:

    ~ $ uname
    

    您将得到一个Operation not permitted输出:

    Operation not permitted
    

这是一个很好的活动,表明如果映像被攻击者访问,我们仍然可以做很多事情来限制对映像的处理。

活动 11.02:扫描您的全景徒步旅行应用映像以查找漏洞

解决方案:

我们可以通过多种方式扫描映像中的漏洞。以下步骤是实现这一点的一种方法,使用 Anchore 来验证postgres-app映像对于我们的应用来说是否安全:

  1. 标记映像并将其推送到 Docker Hub 存储库中。在这种情况下,用我们的存储库名称标记postgres-app映像,并将其标记为activity2。我们还将其推送到我们的 Docker 中心仓库:

    docker tag postgres <your repository namespace>/postgres-app:activity2 ; docker push <your repository name>/postgres-app:activity2
    
  2. 你应该还保留着本章中最初使用的docker-compose.yaml文件。如果您还没有运行 Anchore,运行docker-compose命令并导出ANCHORE_CLI_URLANCHORE_CLI_URLANCHORE_CLI_URL变量,就像您之前所做的那样,以允许我们运行anchore-cli命令:

    docker-compose up -d
    
  3. 通过运行anchore-cli system status命令来检查锚定应用的状态:

    anchore-cli system status
    
  4. 使用feeds list命令检查订阅源列表是否全部更新:

    anchore-cli system feeds list
    
  5. 一旦所有的提要都被更新,添加我们已经推送到 Docker Hub 的postgres-app映像。使用anchore-cli提供的image add命令,提供我们要扫描的映像的存储库、映像和标签。这将把映像添加到我们的 Anchore 数据库,准备扫描:

    anchore-cli image add <your repository namespace>/postgres-app:activity2
    
  6. 使用image list命令,允许我们验证我们的映像已经被分析。一旦完成,您应该会在Analysis Status栏中看到analyzed字样:

    anchore-cli image list
    
  7. Use the image vuln command with our image name to see a list of all the vulnerabilities found on our postgres-app image. This image is a lot larger and a lot more complex than the images we have tested previously, so there is a long list of vulnerabilities found when we use the all option. Fortunately, most of the vulnerabilities present either Negligible or Unknown. Run the image vuln command and pipe out the results to the wc -l command:

    anchore-cli image vuln <your repository namespace>/postgres-app:activity2 all | wc -l
    

    这将为我们提供已发现漏洞的数量。在这种情况下有 100 多个值:

    108
    
  8. Finally, use the evaluate check command to see whether the vulnerabilities found will give us a pass or fail:

    anchore-cli evaluate check <your repository namespace>/postgres-app:activity2
    

    幸运的是,从下面的输出可以看出,我们通过了:

    Image Digest: sha256:57d8817bac132c2fded9127673dd5bc7c3a97654
    636ce35d8f7a05cad37d37b7
    Full Tag: docker.io/vincesestodocker/postgres-app:activity2
    Status: pass
    Last Eval: 2019-11-23T06:15:32Z
    Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
    

由于映像是由大型组织提供的,确保您可以安全使用符合他们的最佳利益,但是由于扫描映像非常容易,我们应该仍然在扫描它们,以验证它们 100%可以安全使用。

12 时。最佳实践

活动 12.01:查看全景徒步应用使用的资源

解决方案:

我们可以通过多种方式来完成本章的第一项活动。以下步骤是一种方法,使用docker stats命令查看全景徒步应用中服务正在使用的资源。在本例中,我们将使用postgresql-app服务,该服务作为全景徒步旅行应用的一部分运行:

  1. Create a script that will create a new table and fill it with random values. The following script does exactly what we want in this situation as we want to create a long processing query and see how it affects the resources on our container. Add in the following details and save the file as resource_test.sql using your favorite editor:

    1 CREATE TABLE test_data
    2 (
    3     random_value NUMERIC NOT NULL,
    4     row1         NUMERIC NOT NULL,
    5     row2         NUMERIC NOT NULL
    6 );
    7 
    8 INSERT INTO test_data
    9     SELECT random_value.*,
    10     gen.* ,
    11     CEIL(RANDOM()*100)
    12     FROM GENERATE_SERIES(1, 300) random_value,
    13     GENERATE_SERIES(1, 900000) gen
    14     WHERE gen <= random_value * 300;
    

    第 1 行第 6 行创建新表并设置它包含的三个不同行,而第 8 行 到第 14 行遍历一个新表,用随机值填充它。

  2. 如果您尚未获得 PostgreSQL Docker 映像的副本,请使用以下命令从支持的 PostgreSQL Docker Hub 存储库中提取映像:

    docker pull postgres
    
  3. Move into a new terminal window and run the docker stats command to view the CPU percentage being used, as well as the memory and memory percentage being used:

    docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}"
    

    在下面的命令中,我们没有显示容器标识,因为我们想要限制输出中显示的数据量:

    NAME         CPU %       MEM %      MEM USAGE / LIMIT
    
  4. 为了简单地测试这个映像,您不需要将正在运行的容器装载到特定的卷上,就可以使用您以前用于这个映像的数据。移动到一个不同的终端来监控你的中央处理器和内存。启动容器并将其命名为postgres-test,并通过公开运行psql命令所需的端口来确保可以从您的主机系统访问数据库。我们还使用环境变量(-e)选项指定了docker的临时密码:

    docker run --rm --name postgres-test -v ${PWD}/resource_test.sql:/resource_test.sql -e POSTGRES_PASSWORD=docker -d -p 5432:5432 postgres
    
  5. 在运行测试脚本之前,请转到监控 CPU 和内存使用情况的终端。您可以看到,我们的容器已经在使用一些资源,甚至没有真正做任何事情:

    NAME            CPU %    MEM %     MEM USAGE / LIMIT
    postgres-test   0.09%    0.47%     9.273MiB / 1.943GiB
    
  6. 使用以下命令进入容器内的 Docker:

    docker exec -it postgres-test /bin/bash
    
  7. 使用psql命令发送postgres-test容器命令,创建一个名为resource_test :

    psql -h localhost -U postgres -d postgres -c 'create database resource_test;'
    Password for user postgres: 
    CREATE DATABASE
    

    的新数据库

  8. Run the script you created earlier. Make sure you include the time command before you run the script as this will allow you to see the time it takes to complete:

    time psql -h localhost -U postgres -d resource_test -a -f resource_test.sql
    

    我们在下面的代码块中减少了命令的输出。用数据填满resource_database表格需要 50 秒:

    Password for user postgres: 
    …
    INSERT 0 13545000
    real    0m50.446s
    user    0m0.003s
    sys     0m0.008s
    
  9. 移动到运行docker stats命令的终端。您将看到一个输出,具体取决于系统运行的内核数量和可用内存。正在运行的脚本似乎不是很占用内存,但是它将容器可用的 CPU 提升到了 100%

    NAME            CPU %      MEM %    MEM USAGE / LIMIT
    postgres-test   100.66%    2.73%    54.36MiB / 1.943GiB
    
  10. 在可以使用对 CPU 和内存配置的更改运行容器之前,使用以下命令删除正在运行的容器,以确保有一个新的数据库正在运行:

```
docker kill postgres-test
```
  1. 再次运行容器。在这种情况下,您将把可用的 CPU 限制在主机系统上一个内核的一半,并且由于测试不是太占用内存,所以将内存限制设置为256MB :
```
docker run --rm --name postgres-test -e POSTGRES_PASSWORD=docker -d -p 5432:5432 --cpus 0.5 --memory 256MB postgres
```
  1. 使用exec命令进入容器:
```
docker exec -it postgres-test /bin/bash
```
  1. 同样,在运行测试之前,创建resource_test数据库:
```
psql -h localhost -U postgres -d postgres -c 'create database resource_test;'
Password for user postgres: 
CREATE DATABASE
```
  1. 现在,要查看我们的资源发生了什么变化,请限制容器可以使用的内容。再次运行resource_test.sql脚本,通过限制资源,特别是 CPU,我们可以看到现在需要 1 分多钟才能完成:
```
time psql -h localhost -U postgres -d resource_test -a -f resource_test.sql
Password for user postgres: 
…
INSERT 0 13545000
real    1m54.484s
user    0m0.003s
sys     0m0.005s
```
  1. 移动到运行docker stats命令的终端。它也应该看起来不同,因为可使用的 CPU 百分比将减半。您对 CPU 所做的更改减缓了脚本的运行速度,因此似乎也减少了正在使用的内存:
```
NAME            CPU %     MEM %      MEM USAGE / LIMIT
postgres-test   48.52%    13.38%     34.25MiB / 256MiB
```

这个活动很好地说明了在监视和配置容器资源时,有时需要执行的平衡操作。它确实阐明了您需要了解您的服务正在执行的任务,以及配置的更改将如何影响您的服务的运行。

活动 12.02:使用 hadolint 改进 Docker 文件的最佳实践

解决方案

我们可以通过多种方式进行这项活动。以下步骤展示了一种实现方法:

  1. 使用以下docker pull命令从hadolint存储库中提取映像:

    docker pull hadolint/hadolint
    
  2. Use hadolint to lint the docker-stress Dockerfile we have been using throughout this chapter and document the warnings presented:

    docker run --rm -i hadolint/hadolint < Dockerfile
    

    您将收到如下警告:

    /dev/stdin:1 DL3006 Always tag the version of an image explicitly
    /dev/stdin:2 DL3008 Pin versions in apt get install. Instead of 
    'apt-get install <package>' use 'apt-get install 
    <package>=<version>'
    /dev/stdin:2 DL3009 Delete the apt-get lists after installing 
    something
    /dev/stdin:2 DL3015 Avoid additional packages by specifying 
    '--no-install-recommends'
    /dev/stdin:2 DL3014 Use the '-y' switch to avoid manual input 
    'apt-get -y install <package>'
    /dev/stdin:3 DL3025 Use arguments JSON notation for CMD 
    and ENTRYPOINT arguments
    

    与最初测试映像时相比,没有真正的变化。但是Dockerfile中只有三行代码,看能否减少hadolint呈现的警告数量。

  3. 如本章前面所述,hadolint维基页面将为您提供如何解决每个警告的详细信息。但是,如果您遍历每一行,您应该能够解决所有这些警告。第一个显示的是DL3006,要求标记您正在使用的 Docker 映像的版本,这是 Ubuntu 映像的新版本。将您的Dockerfile第 1 行更改为现在包括18.08映像版本,如图所示:

    1 FROM ubuntu:18.08
    
  4. 接下来的四个警告都和我们Dockerfile的第二行有关。DL3008要求锁定正在安装的应用版本。在以下情况下,将应力应用固定到版本 1.0.3。DL3009声明你应该删除任何列表。这就是我们在下面的代码中添加了第 4 行第 5 行的地方。DL3015声明你也应该使用--no-install-recommends,确保你没有安装你不需要的应用。最后,DL3014建议您包括-y选项,以确保不会提示您验证应用的安装。编辑Dockerfile如下所示:

    2 RUN apt-get update \
    3 && apt-get install -y stress=1.0.4 --no-install-recommends \
    4 && apt-get clean \
    5 && rm -rf /var/lib/apt/lists/*
    
  5. DL3025 is your last warning and states that you need to have your CMD instruction in JSON format. This could cause issues as you are trying to use environment variables with your stress application. To clear up this warning, run the stress command with the sh -c option. This should still allow you to run the command with environment variables:

    6 CMD ["sh", "-c", "stress ${var}"]
    

    您现在遵循最佳实践的完整Dockerfile应该如下所示:

    FROM ubuntu:18.04
    RUN apt-get update \
     && apt-get install -y stress=1.0.4 --no-install-recommends \
     && apt-get clean \
     && rm -rf /var/lib/apt/lists/*
    CMD ["sh", "-c", "stress ${var}"]
    
  6. 现在,再次使用hadolint去除Dockerfile的绒毛,不再出现警告:

    docker run --rm -i hadolint/hadolint < Dockerfile
    
  7. If you want to be 100% sure that the Dockerfile is looking as good as it can be, perform one final test. Open FROM:latest in your browser and you will see the Dockerfile with the latest changes showing No problems or suggestions found!:

    Figure 12.4: The docker-stress Dockerfile now adhering to the best practices

图 12.4:Docker 压力 Docker 文件现在坚持最佳实践

您的Dockerfiles可能比本章中介绍的要大得多,但是正如您所看到的,系统的逐行方法将帮助您纠正您的Dockerfiles可能存在的任何问题。使用诸如hadolintFROM latest之类的应用,以及它们关于如何解决警告的建议,将使您熟悉最佳实践。这就把我们的活动和这一章带到了最后,但还有更多有趣的内容要走,所以现在不要停下来。

13。监控 Docker 指标

活动 13.01:创建 Grafana 仪表板来监控系统内存

解决方案:

您可以通过多种方式来执行此活动。以下步骤就是这样一种方法:

  1. 确保普罗米修斯正在运行并收集数据,Docker 和cAdvisor被配置为公开度量,Grafana 正在运行并以普罗米修斯为数据源进行配置。

  2. 打开 Grafana 网络界面和您在练习 13.05:在您的系统上安装和运行 Grafana中创建的Container Monitoring仪表板

  3. There is an Add panel option at the top of the dashboard and to the right of the dashboard name. Click the Add panel icon to add in your new dashboard panel:

    Figure 13.26: Adding a new panel to the container monitoring dashboard

    图 13.26:向容器监控仪表板添加一个新面板

  4. 从下拉列表中选择Prometheu s 作为我们将用于生成新仪表板面板的数据源。

  5. metrics部分,添加以下 PromQL 查询,container_memory_usage_bytes,只搜索具有名称值的条目。然后,对每个名称求和,为每个容器提供一个线图:

    sum by (name) (container_memory_usage_bytes{name!=""})
    
  6. Depending on the amount of data you have available in your time-series database, adjust the relative time if needed. Perhaps set the relative time to 15m. The previous three steps are captured in the following diagram:

    Figure 13.27: Adding a new panel to the Container Monitoring dashboard

    图 13.27:向容器监控仪表板添加一个新面板

  7. 选择Show options并添加Memory Container Usage的标题。

  8. If you click on Save, you will notice that you cannot save the panel as the dashboard has been provisioned on startup. You can export the JSON, which you can then add to your provisioning directory. Click the Share Dashboard button and export the JSON. Select Save JSON to file and store the dashboard file in the /tmp directory:

    Figure 13.28: Warning that we cannot save the new dashboard

    图 13.28:警告我们不能保存新的仪表板

  9. 停止运行您的 Grafana 容器,以便可以在您的环境中添加到配置文件。使用以下docker kill命令进行操作:

    docker kill grafana
    
  10. provisioning/dashboards目录中已经有一个名为ContainerMonitoring.json的文件。从您的tmp目录复制您刚刚创建的 JSON 文件,并替换provisioning/dashboards目录中的原始文件:

```
cp /tmp/ContainerMonitoring-1579130313205.json provisioning/dashboards/ContainerMonitoring.json
```
  1. 再次启动 Grafana 映像,并使用默认管理密码登录应用:
```
docker run --rm -d --name grafana -p 3000:3000 -e "GF_SECURITY_ADMIN_PASSWORD=secret" -v ${PWD}/provisioning:/etc/grafana/provisioning grafana/Grafana
```
  1. Log in to Grafana one more time and move to the Container Monitoring dashboard you have been provisioning. You should now see the newly created Memory Container usage panel at the top of our dashboard, similar to the following screenshot:
![Figure 13.29: New dashboard panel displaying memory usage ](img/B15021_13_24.jpg)

图 13.29:显示内存使用情况的新仪表板面板

现在,这应该可以更容易地监控系统上运行的容器的内存和 CPU 使用情况。仪表板提供了比浏览docker stats命令更简单的界面,尤其是当您开始在系统上运行更多的容器时。

活动 13.02:配置全景徒步旅行应用,向普罗米修斯展示指标

解决方案:

我们可以通过多种方式进行这项活动。在这里,我们选择向我们作为全景徒步应用的一部分运行的 PostgreSQL 容器中添加一个导出器:

  1. If you don't have the panoramic trekking app running, make sure that at least the PostgreSQL container is running so that you can complete this activity. You won't need to have Prometheus running yet as you will need to make some changes to the configuration file first. Run the following command to verify that the PostgreSQL database is running:

    docker run --rm -d --name postgres-test -e POSTGRES_PASSWORD=docker -p 5432:5432 postgres
    

    为了从您的 PostgreSQL 容器中收集更多的指标,您可以在 GitHub 上找到用户已经创建的导出器albertodonato。使用别人已经创建的比创建自己的要容易得多。文档和详细信息可在以下网址找到:https://github.com/albertodonato/query-exporter

  2. The aforementioned GitHub account has a good breakdown of how to set up the configuration and metrics. Set up a basic configuration file to get started. Find the IP address that the PostgreSQL container is running on by running the following docker inspect command. This gives you the internal IP address your container is running on. You'll also need to substitute the container name you have running for <container_name>:

    docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container_name>
    

    您的 IP 地址可能与这里的不同:

    172.17.0.3
    
  3. 对于这个导出器,您需要设置一些额外的配置来输入导出器。首先,在工作目录中创建一个名为psql_exporter_config.yml的配置文件,并用文本编辑器打开该文件。

  4. 在下面的配置文件中输入前四行。这是导出器连接到数据库的方式。您需要提供可以访问数据库的密码,以及您在上一步中获得的 IP 地址,或者是否为数据库分配了域:

    1 databases:
    2   pg:
    3     dsn: postgresql+psycopg2://postgres:<password>@<ip|domain>/        postgres
    4
    
  5. 将第一个指标添加到配置文件中。输入以下行来添加您的度量名称、仪表类型、描述和标签:

    5 metrics:
    6   pg_process:
    7     type: gauge
    8     description: Number of PostgreSQL processes with their         states
    9     labels: [state]
    10
    
  6. Set up a database query to gather the metric details you want for the pg_process gauge. Line 13 shows that you want to create a database query with lines 14 and 15, assigning the results to the metric you created earlier. Lines 16 to 23 are the query we want to run on our database in order to create a gauge for the number of processes running on the database:

    psql_exporter_config.yml

    11 queries:
    12   process_stats:
    13     databases: [pg]
    14     metrics:
    15       - pg_process
    16     sql: >
    17       SELECT
    18         state,
    19         COUNT(*) AS pg_process
    20       FROM pg_stat_activity
    21       WHERE state IS NOT NULL
    22       GROUP BY state
    23       FROM pg_stat_database
    

    你可以在这里找到完整的代码https://packt.live/32C47K3

  7. 保存配置文件,并从命令行运行导出程序。出口商将在港口公布其指标。装载您在本练习前面创建的配置文件。您还将获得最新版本的adonato/query-exporter映像:

    docker run -p 9560:9560/tcp -v --name postgres-exporter ${PWD}/psql_exporter_config.yml:/psql_exporter_config.yml --rm -itd adonato/query-exporter:latest -- /psql_exporter_config.yml
    
  8. 打开网络浏览器,使用网址http://0.0.0.0:9560/metrics查看您为作为全景徒步旅行应用的一部分运行的 PostgreSQL 容器设置的新指标:

    # HELP database_errors_total Number of database errors
    # TYPE database_errors_total counter
    # HELP queries_total Number of database queries
    # TYPE queries_total counter
    queries_total{database="pg",status="success"} 10.0
    queries_total{database="pg",status="error"} 1.0
    # TYPE queries_created gauge
    queries_created{database="pg",status="success"} 
    1.5795789188074727e+09
    queries_created{database="pg",status="error"} 
    1.57957891880902e+09
    # HELP pg_process Number of PostgreSQL processes with their states
    # TYPE pg_process gauge
    pg_process{database="pg",state="active"} 1.0
    
  9. 移动到安装了普罗米修斯的目录中,用文本编辑器打开prometheus.yml文件,并添加导出器详细信息,让普罗米修斯开始收集数据:

    45   - job_name: 'postgres-web'
    46     scrape_interval: 5s
    47     static_configs:
    48     - targets: ['0.0.0.0:9560']
    
  10. 保存您对prometheus.yml文件所做的更改,并从命令行再次启动普罗米修斯应用,如下所示:

```
./prometheus --config.file=prometheus.yml
```
  1. If everything has worked as it should, you should now see the postgres-web target displayed on the Prometheus Targets page, as demonstrated here:
![Figure 13.30: New postgres-web Targets page displayed on Prometheus ](img/B15021_13_25.jpg)

图 13.30:普罗米修斯上显示的新 postgres-web 目标页面

这就把我们带到了活动的结尾和本章的结尾。这些活动应该有助于巩固之前所学的知识,并为您提供收集应用和运行系统的指标以及以更方便用户的方式显示它们的经验。

14。收集容器日志

活动 14.01:为 Splunk 安装创建 docker-compose.yml 文件

解决方案:

我们可以通过多种方式进行这项活动。以下步骤概述了一种可能的方法。

在这里,您将设置一个docker-compose.yml文件,该文件将至少以本章中相同的方式运行您的 Splunk 容器。为了安装/opt/splunk/etc目录和/opt/splunk/var目录,您将设置两个卷。您需要公开端口800099978088,以允许访问您的 web 界面并允许数据转发到 Splunk 实例。最后,您需要设置一些环境变量来接受 Splunk 许可证并添加管理员密码。让我们开始吧:

  1. 创建一个名为docker-compose.yml的新文件,用你喜欢的文本编辑器打开。

  2. 从您喜欢的版本Docker Compose开始,创建您要使用的卷,以便挂载varext目录:

    1 version: '3'
    2
    3 volumes:
    4   testsplunk:
    5   testsplunkindex:
    6
    
  3. 为 Splunk 安装设置服务,使用splunk作为主机名,使用splunk/splunk作为您安装时使用的映像。另外,设置SPLUNK_START_ARGSSPLUNK_PASSWORD的环境变量,如下图:

    7 services:
    8   splunk:
    9     hostname: splunk
    10    image: splunk/splunk
    11    environment:
    12      SPLUNK_START_ARGS: --accept-license
    13      SPLUNK_PASSWORD: changeme
    
  4. 最后,安装卷并展示您的安装访问 web 界面和转发来自转发器和容器的数据所需的端口:

    14    volumes:
    15      - ./testsplunk:/opt/splunk/etc
    16      - ./testsplunkindex:/opt/splunk/var
    17    ports:
    18      - "8000:8000"
    19      - "9997:9997"
    20      - "8088:8088"
    
  5. Run the docker-compose up command to make sure it is all working correctly. Use the -d option to make sure it is running as a daemon in the background of our system:

    docker-compose up -d
    

    该命令应返回类似如下的输出:

    Creating network "chapter14_default" with the default driver
    Creating chapter14_splunk_1 ... done
    
  6. Once your Splunk installation is running again, it's time to get one of your services from the Panoramic Trekking App running so that you can forward logs to Splunk to be indexed. When using the docker run command, add the log driver details, as you did previously in this chapter, and make sure you include the correct token for your HTTP Event Collector:

    docker run --rm -d --name postgres-test \
    -e POSTGRES_PASSWORD=docker -p 5432:5432 \
    --log-driver=splunk \
    --log-opt splunk-url=http://127.0.0.1:8088 \
    --log-opt splunk-token=5c051cdb-b1c6-482f-973f-2a8de0d92ed8 \
    --log-opt splunk-insecureskipverify=true \
    --log-opt tag="{{.Name}}/{{.FullID}}" \
    postgres -c log_statement=all 
    

    注意

    请注意,我们在docker run命令中使用了-c log_statement=all,因为这将确保我们所有的 PostgreSQL 查询都被记录并发送到 Splunk。

  7. Log in to the Splunk web interface and access the Search & Reporting app. Enter the source="http:docker logs" AND postgres-test query into the interface and press Enter. Since you have tagged our container, you should see your containers tagged with the name and full ID, so adding postgres-test to your search will make sure only your PostgreSQL logs are visible:

    Figure 14.48: PostgreSQL logs displaying in Splunk

图 14.48:Splunk 中显示的 PostgreSQL 日志

从前面的截图中可以看到,我们的日志成功地流过了 Splunk。记下添加到日志条目中的标记,如前面的截图所示。

这个活动教我们如何使用 Docker Compose 在我们的开发项目中实现日志记录过程。

活动 14.02:创建 Splunk 应用来监控全景徒步应用

解决方案:

您可以通过多种方式来执行此活动。以下步骤是实现这一点的一种方法。在这里,您将向作为全景徒步应用一部分运行的PostgreSQL容器添加一个导出器:

  1. 确保 Splunk 正在运行,并且您一直监控的服务已经运行了一段时间,以确保您正在为此活动收集一些日志。

  2. Log in to the Splunk web interface. From the Splunk home screen, click on the cog icon next to the Apps menu; you will be presented with the Apps page for your Splunk environment:

    Figure 14.49: Apps page of the Splunk environment

    图 14.49:Splunk 环境的应用页面

  3. Click the Create app button and fill in the form. It will be similar to the following, in which Name is set to Panoramic Trekking App, Folder name is set to panoramic_trekking_app, and Version is set to 1.0.0. Click Save to create the new app:

    Figure 14.50: Creating your new app in Splunk

    图 14.50:在 Splunk 中创建新应用

  4. Return to the Splunk home page and make sure your Panoramic Trekking App is visible from the Apps menu. Click Panoramic Trekking App to bring up the Search & Reporting page so that you can start querying your data:

    Figure 14.51: Selecting Panoramic Trekking App

    图 14.51:选择全景徒步应用

  5. Type source="http:docker logs" AND postgres-test AND INSERT AND is_superuser | stats count into the query bar and press Enter. The search will look for any Super Users that were created as part of the application. When your data comes up, click the Visualization tab and change it to display a single-value visualization:

    Figure 14.52: Entering a query in the query bar

    图 14.52:在查询栏中输入查询

  6. Click the Save As button at the top of the screen and select the Dashboards panel. When you are presented with this screen, select the panel to be added to a new dashboard and give it the name PTA Monitoring. Also, give the panel the title Super User Access and click Save:

    Figure 14.53: Adding details to the dashboard panel

    图 14.53:向仪表板面板添加细节

  7. When you are presented with your new dashboard, click the Edit and Add panel buttons. Select New and then Single Value as the visualization type. Set Content Title to Database Creation. Add the source="http:docker logs" AND postgres-test AND CREATE DATABASE | stats count source string and click Save. This will search through your logs to show if anyone has created any databases on the PostgreSQL database, which should only happen when the app is set up and created:

    Figure 14.54: Editing the dashboard panel

    图 14.54:编辑仪表板面板

  8. 再次单击New Panel按钮,从可视化效果中选择NewColumn Chart。添加App UsageContent Title,添加source="http:docker logs" AND postgres-test AND SELECT AND photo_viewer_photo earliest=-60m | timechart span=1m count搜索查询,点击Save。该搜索将为您提供一段时间内使用该应用查看您照片的人数。

  9. Feel free to move the panels around the dashboard. When you are happy with the changes, click the Save button. Your dashboard should look similar to the following:

    Figure 14.55: New dashboard panel used to monitor PostgreSQL usage

图 14.55:用于监控 PostgreSQL 使用情况的新仪表板面板

这项活动帮助您为全景徒步旅行应用收集日志数据,并使用 Splunk 以更加用户友好的方式显示这些数据。

15。用插件扩展 Docker

活动 15.01:安装带有网络和卷插件的 WordPress

解决方案:

通过以下步骤,可以使用卷和网络插件为数据库和 WordPress 博客创建容器:

  1. Create a network with the following command:

    docker network create  \
    --driver=store/weaveworks/net-plugin:2.5.2 \
    --attachable \
    wp-network
    

    该命令使用编织网插件创建一个网络,用driver标志指定。此外,卷被指定为attachable,这意味着您将来可以连接到 Docker 容器。最后,容器的名称将是wp-network。您应该得到如下输出:

    mk0pmhpb2gx3f6s00o57j2vd
    
  2. Create a volume with the following command:

    docker volume create -d vieux/sshfs \
    --name wp-content \
    -o sshcmd=root@localhost:/tmp \
    -o password=root \
    -o port=2222
    

    该命令使用vieux/sshfs插件通过 SSH 创建一个卷。该卷的名称为wp-content,并为ssh命令、端口和密码传递了其他选项:

    wp-content
    
  3. Create the mysql container with the following command:

    docker run --name mysql -d \
    -e MYSQL_ROOT_PASSWORD=wordpress \
    -e MYSQL_DATABASE=wordpress \
    -e MYSQL_USER=wordpress \
    -e MYSQL_PASSWORD=wordpress \
    --network=wp-network \
    mysql:5.7
    

    该命令以分离模式运行mysql容器,使用环境变量和wp-network连接。

  4. Create the wordpress container with the following command:

    docker run --name wordpress -d \
    -v wp-content:/var/www/html/wp-content \
    -e WORDPRESS_DB_HOST=mysql:3306 \
    -e WORDPRESS_DB_USER=wordpress \
    -e WORDPRESS_DB_PASSWORD=wordpress \
    -e WORDPRESS_DB_NAME=wordpress \
    --network=wp-network \
    -p 8080:80 \
    wordpress
    

    该命令使用环境变量和wp-network连接以分离模式运行wordpress容器。此外,容器的80港在主机系统的8080港可用。

    成功启动后,您将有两个容器运行mysqlwordpress:

    docker ps
    

    Figure 15.17: The WordPress and database containers

    图 15.17:WordPress 和数据库容器

  5. Open http://localhost:8080 in your browser to check the WordPress setup screen:

    Figure 15.18: WordPress setup screen

图 15.18: WordPress 设置屏幕

WordPress 安装屏幕验证是否使用网络和卷插件安装了 WordPress。

在本练习中,您已经使用编织网插件创建了一个自定义网络,并使用sshfs插件创建了一个自定义卷。您创建了一个使用自定义网络的数据库容器和一个使用自定义网络和自定义卷的 WordPress 容器。设置成功后,您的 Docker 容器通过自定义网络相互连接,并通过 SSH 使用卷。在本练习中,您将 Docker 扩展用于实际应用。现在,您可以放心地用您的定制业务需求和技术扩展 Docker。