Docker、Docker Compose、Harbor 的使用

Docker 引擎是一种用于构建和容器化应用程序的开源容器化技术。它是一个服务端-客户端结构的应用,主要有以下部分组成:

  1. Docker 守护进程:持久化的进程,监听 Docker Engine API 的请求
  2. Docker Engine API:与 Docker 守护进程交互用的的 RESTful API
  3. Docker 客户端:命令行接口,通过客户端将命令发送给守护进程

Dockerfile 一个文本文档,Docker 可以通过读取 Dockerfile 中定义的指令来自动构建镜像。

Docker Compose 是一个用于定义和运行多个容器的 Docker 工具。Compose 使用 YAML 文件来配置应用程序的服务。然后,通过单个命令,就可以从配置中创建并启动所有服务。

下面演示所用 Demo 地址:https://github.com/14032/gchat

Dockerfile

Docker 提供了一种构建镜像方式叫 Dockerfile,下面是用来构建 gchat 项目镜像的 Dockerfile 文件:

FROM maven:3-jdk-8-alpine
MAINTAINER "人间春荡荡 <人间春荡荡@126.com>"

WORKDIR /opt/gchat
ADD gchat.war .
RUN jar -xvf gchat.war

ENV TZ=Asia/Shanghai
EXPOSE 8080

ENTRYPOINT java -cp /opt/gchat org.springframework.boot.loader.WarLauncher
  1. FROM 用来指定镜像所依赖的基础镜像,这里项目需要的是 JDK 环境
  2. MAINTAINER:作者信息
  3. WORKDIR:指定后续命令执行的目录,即后续的命令都将 /opt/gchat 作为当前目录
  4. ADD:复制文件,将当前目录下 gchat.war 包复制到镜像 /opt/gchat/ 目录下
  5. RUN:在容器中要执行的 shell 命令
  6. ENV:指定环境变量,这里指定了时区
  7. EXPOSE:声明服务监听端口(仅仅是声明,并不会主动做端口映射)
  8. ENTRYPOINT:指定镜像的入口启动进程

Dockerfile 编写完了,下面看下如何使用 Dockerfile 文件来生成镜像。

#  构建镜像命令
docker build -t gchat:1.0-SNAPSHOT .

-t 作用是给镜像打个标签,起个名字。

末尾 . 代表 Dockerfile 文件在当前操作的目录下,否则可以通过 -f /opt/Dockerfile 参数来指定文件位置。

docker build 会加载当前目录下的 Dockerfile 文件,然后按照顺序,执行文件中定义的命令。

docker build 执行完成后,通过 docker images 命令查看镜像列表:

$ docker images
REPOSITORY    TAG             IMAGE ID        CREATED         SIZE
gchat         1.0-SNAPSHOT    d97ec5bc1022    4 months ago    241MB

通过 docker run 来创建运行 gchat 容器:

docker run -d --network=host --name gchat \
--env jdbc.type="mysql" \
--env jdbc.username="root" \
--env jdbc.password="root" \
--env jdbc.driver="com.mysql.cj.jdbc.Driver" \
--env jdbc.url="jdbc:mysql://192.168.0.10:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai" gchat:1.0-SNAPSHOT192

参数 --network 用来指定容器运行的网络模式,默认为 bridge 方式。host 则表示主机网络模式,共享宿主机的网络栈;若采用默认的 bridge 方式,则需要开启端口映射 -p 8080:8082 ,将容器内的 8082 端口映射在宿主机的 8080 端口供外部访问。

http://127.0.0.1:8080/gchat

运行过程中,可通过 docker logs -f gchat 来查看容器项目日志输出。

通过 docker ps 查看运行中的容器列表:

$ docker ps
CONTAINER ID  IMAGE                COMMAND                 CREATED     STATUS        PORTS   NAMES
12483291aa72  gchat:1.0-SNAPSHOT   "/bin/sh -c 'java -c…"  2 minutes   Up a minute           gchat

查看详细信息使用 docker inspect 命令:

# 查看 gchat 容器信息
docker inspect gchat

# 查看 gchat 镜像的信息:
docker image inspect gchat:1.0-SNAPSHOT

还有一种生成镜像的方式是:docker commit

这个命令可以把一个正在运行的容器,直接提交为一个镜像。

例如在内网环境安装 Jenkins ,不能访问互联网,这个时候就可以先在本地运行 Jenkins 容器:

docker run -d --name jenkins -p 8084:8080 jenkins/jenkins:lts

运行成功后,访问 http://127.0.0.1:8084/jenkins ,把需要的一些插件全部安装后,对正在运行的容器执行 docker commit 操作,这样在容器之上的所有操作都会保存到新的镜像里。

# 将运行中的容器 56b5168a7ae2 提交为镜像 
docker commit 56b5168a7ae2 jenkins:self-v3

之后,可通过 docker save 命令导出镜像,再通过 docker load 命令将镜像加载至内网中。

# 导出
docker save -o jenkins-lts-v3.tar jenkins:self-v3
# 导入
docker load -i jenkins-lts-v3.tar jenkins:self-v3

当然还可以通过 Volume 数据卷的功能,将宿主机目录挂载到 Jenkins 所在容器内的安装目录上,这样所有的有关 Jenkins 文件增删改都发生在宿主机上。

# 将 /opt/jenkins 挂载至容器内 jenkins 的安装目录
-v /opt/jenkins:/home/jenkins

如果想在运行中的容器中执行 shell 命令,使用 docker exec 命令:

docker exec -it gchat /bin/sh

命令执行后会进入容器的默认工作目录,如果在 Dockerfile 中指定了工作目录 WORKDIR,则会进入 Dokcerfile 指定的目录,例如执行 ls 默认显示的就是 /opt/gchat 下的文件。

$ docker exec -it gchat ls
META-INF   WEB-INF    gchat.war  org

查看设置的环境变量 env:

$ docker exec -it gchat env

# Dockerfile 镜像中指定
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
HOSTNAME=f3b50c9fcb00
LANG=C.UTF-8
JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk
JAVA_VERSION=8u212
JAVA_ALPINE_VERSION=8.212.04-r0
MAVEN_HOME=/usr/share/maven
MAVEN_CONFIG=/root/.m2
JAVA_OPTS=-Xms1024m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
HOME=/root

# 创建容器时指定
jdbc.type=mysql
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://mysql:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
TZ=Asia/Shanghai

执行 uname -a,查看 Linux 内核版本:

# 容器内执行
$ docker exec -it gchat /bin/sh
/opt/gchat # uname -a
Linux king-ubuntu 4.15.0-108-generic #109-Ubuntu SMP Fri Jun 19 11:33:10 UTC 2020 x86_64 Linux
/opt/gchat # exit
# 宿主机
$ uname -a
Linux king-ubuntu 4.15.0-108-generic #109-Ubuntu SMP Fri Jun 19 11:33:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

首先要明确的是,容器与宿主机共享操作系统内核,也就是说容器和镜像是没有内核的,只有文件系统。我们有些服务器是华为 TaiShan,基于鲲鹏处理器 ARM 架构的 Linux 系统,在刚开始使用 Docker 的时候,尝试在其中启动基于 X86 架构构建的镜像,很显然失败了。

下面是官方文档中 Docker 的特性说明,其中约束和隔离涉及到 Linux 的 Namespace 和 Cgroups 特性,大家可自行 Google 了解。

灵活:即使是最复杂的应用程序也可以被容器化。
轻量级:容器利用并共享主机内核,使它们在系统资源方面比虚拟机效率更高。
可移植:您可以在本地构建、部署到云中,并在任何地方运行。
松散耦合:容器是高度自给自足和封装的,允许您替换或升级一个容器,而不会破坏其他容器。
可扩展:您可以增加和自动分发跨数据中心的容器副本。
安全:容器对进程进行约束和隔离,而不需要用户进行任何配置。

容器只是操作系统中的一个进程:

从根本上说,容器只不过是一个正在运行的进程,为了保持它与主机和其他容器的隔离,对它应用了一些附加的封装特性。容器隔离最重要的是每个容器与自己的私有文件系统交互;这个文件系统由 Docker 镜像提供。镜像包括运行应用程序所需的一切代码或二进制、运行时、依赖项和任何其他所需的文件系统对象。

# 查看进程号
$ docker top gchat
UID     PID      PPID    C    STIME    TTY    TIME           CMD
root    4038     4014    6    13:57     ?     00:00:14       java -cp ...

Harbor

Harbor 是构建企业级私有 Docker 镜像仓库的开源解决方案,就像 Nexus 是 Maven 的 JAR 仓库管理器一样。

Harbor 使用 Docker 方式来安装启动,并且通过 Docker Compose 工具来管理,所以请先确保 Docker 环境和 Docker Compose 工具已经成功安装。

Harbor 离线安装包 harbor-offline-installer-v1.9.4.tgz 下载地址:

https://github.com/goharbor/harbor/releases

将安装包解压,Harbor 的配置文件 harbor.yml ,包括域名、端口号、初始密码等配置:

# Configuration file of Harbor
hostname: 192.168.0.110
# http related config
http:
  port: 8089
harbor_admin_password: Harbor12345
......

在解压后的文件夹下执行 ./install.sh 命令进行安装,输出如下:

[Step 0]: checking installation environment ...
Note: docker version: 19.03.5
Note: docker-compose version: 1.25.3

[Step 1]: loading Harbor images ...
Loaded image: goharbor/harbor-core:v1.9.4
Loaded image: goharbor/clair-photon:v2.1.0-v1.9.4
... 略
[Step 2]: preparing environment ...
prepare base dir is set to /usr/local/harbor
Clearing the configuration file: /config/db/env
... 略
[Step 3]: starting Harbor ...
Creating harbor-log ... done
Creating registry      ... done
... 略
✔ ----Harbor has been installed and started successfully.----

安装成功后,文件夹下会出现一个 docker-compose.yml 文件,YML 文件中定义了 Harbor 工具所需要创建的容器以及其它配置。可以通过 Docker Compose 命令来启动、停止、卸载 Harbor 服务,关于 Docker Compose 的使用下面会介绍。

  • 创建 Harbor 服务所需容器并且启动

    docker-compose -f /usr/local/harbor/docker-compose.yml -p harbor up -d

  • 停止并删除 Harbor 服务所需容器

    docker-compose -f /usr/local/harbor/docker-compose.yml down

  • 启动、停止、重启 Harbor 服务

    docker-compose -f /usr/local/harbor/docker-compose.yml start/stop/restart

安装成功后,执行下 docker images 命令,查看此时的镜像列表,输出如下,这些镜像皆是在执行 ./install.sh 命令时构建的,即上面输出中的 [Step 1]: loading Harbor images

goharbor/chartmuseum-photon    v0.9.0-v1.9.4    7fd23c6f1f36    127MB
goharbor/harbor-migrator       v1.9.4           899a03b70174    363MB
goharbor/redis-photon          v1.9.4           48c941077683    113MB
goharbor/clair-photon          v2.1.0-v1.9.4    ea69a6daa928    170MB
goharbor/notary-server-photon  v0.6.1-v1.9.4    3a02116cf089    143MB
goharbor/notary-signer-photon  v0.6.1-v1.9.4    289af497dbf0    140MB
goharbor/harbor-registryctl    v1.9.4           7259026fb1bb    103MB
goharbor/nginx-photon          v1.9.4           364c17f09df9    44MB
goharbor/harbor-log            v1.9.4           e0188c234aa2    82.3MB
goharbor/harbor-jobservice     v1.9.4           207acbcff6f5    141MB
goharbor/harbor-core           v1.9.4           a805deab5833    156MB
goharbor/harbor-portal         v1.9.4           cfd272546394    51.4MB
goharbor/harbor-db             v1.9.4           265c8c83954e    150MB
goharbor/prepare               v1.9.4           b2cded69458d    151MB

再执行一下 docker ps 命令,查看此时有哪些运行中的容器,输出如下,这些就是 Harbor 服务所需要的容器,它们的创建和启动是在 ./install.sh 执行的第三步完成的 [Step 3]: starting Harbor ...

CONTAINER ID   IMAGE                               NAMES
751a81c67e99   goharbor/nginx-photon:v1.9.4        nginx
7cb50d0224d4   goharbor/harbor-jobservice:v1.9.4   harbor-jobservice
c2751b9f1d81   goharbor/harbor-core:v1.9.4         harbor-core
2344cd81a05a   goharbor/redis-photon:v1.9.4        redis
89a8695d234a   goharbor/harbor-registryctl:v1.9.4  registryctl
f9c564f44ef2   goharbor/harbor-portal:v1.9.4       harbor-portal
c4661ab61769   goharbor/harbor-db:v1.9.4           harbor-db
86984dbff640   goharbor/registry-photon:v1.9.4     registry
3c36fe8023ef   goharbor/harbor-log:v1.9.4          harbor-log

浏览器访问 Harbor 控制台,账号:admin 默认密码:Harbor12345

Harbor Admin

Docker Maven Plugin

上面通过手动执行 docker build 命令已经成功构建了镜像,这里再看下如何在项目通过 Maven 插件来自动构建镜像并且发布至仓库 Harbor 中。

笔者是在 Windows 的 IDEA 中构建,Docker 是通过虚拟机安装的,所以首先需要配置 Docker 允许远程连接。

编辑 vim /lib/systemd/system/docker.service ,将 ExecStart 追加参数 -H tcp://0.0.0.0:2375

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

保存后,重启:

systemctl daemon-reload
systemctl restart docker

通过浏览器访问 http://192.168.0.110:2375/info 成功即可。

在 IDEA 中添加 Docker 配置:

在 IDEA 中查看 Docker 容器、镜像信息:

docker maven 插件配置:具体参看 Spring Boot Demo 项目

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <configuration>
        <serverId>docker-harbor</serverId>
        <dockerHost>http://192.168.0.110:2375</dockerHost>
        <registryUrl>192.168.0.110:8089</registryUrl>
        <imageName>192.168.0.110:8089/base/${project.build.finalName}:${project.version}</imageName>
        <dockerDirectory>${project.basedir}/bin/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.war</include>
            </resource>
        </resources>
        <imageTags>
            <imageTag>${project.version}</imageTag>
        </imageTags>
        <forceTags>true</forceTags>
        <pushImage>true</pushImage>
    </configuration>
</plugin>
  1. dockerHost 标签可以指定 Docker 服务远程地址
  2. registryUrl 指定仓库地址,这里用的是自己搭建的 Harbor 镜像仓库
  3. imageName 指定镜像名称
  4. dockerDirectory 用来指定 Dockerfile 文件的位置
  5. imageTags 即指定镜像版本号
  6. pushImage 表示是否将镜像推送到指定的仓库中,为 false 时,构建成功后不推送仓库

构建前首先在 Maven 配置中添加 Harbor 用户名密码和 plugin 配置:

<server>  
  <id>docker-harbor</id>  
  <username>admin</username>
  <password>Harbor12345</password>
</server> 
<pluginGroups>
    <pluginGroup>com.spotify</pluginGroup>
</pluginGroups>

下面执行命令进行构建并上传至 Harbot:

mvn clean package docker:build -Dmaven.test.skip=true -Pdocker

输出如下:

[INFO] Building image 192.168.0.110:8089/base/gchat:1.0
Step 1/9 : FROM maven:3-jdk-8-alpine
 ---> 7445f83cd169
Step 2/9 : MAINTAINER "人间春荡荡 <人间春荡荡@126.com>"
 ---> 6ec6024e4273
Step 3/9 : WORKDIR /opt/gchat
 ---> f48609ccaa2d
Step 4/9 : ADD gchat.war .
 ---> 7335b0f3485c
Step 5/9 : RUN jar -xvf gchat.war
... 略
Successfully built 6ce252273598
Successfully tagged 192.168.0.110:8089/base/gchat:1.0

构建成功后,登录 Harbor,http://192.168.0.110/harbor 查看镜像信息。

局域网内可通过 docker pull 拉取 Harbor 上的镜像:

docker pull 192.168.0.110:8089/base/gchat:1.0

docker push 默认推送地址是 Docker 官方仓库 https://hub.docker.com/ ,你需要先注册一个 Docker Hub 账号,然后用 docker login 命令登录后即可执行 docker push 推送镜像。 如要将本地镜像推送至私人搭建的仓库 Harbor,登录时要指定镜像仓库地址:

docker login 192.168.0.110:8089

Docker Compose

编排工具就是来管理 Docker 容器的定义、配置和创建,笔者在 docker-compose.yml 文件中定义了三个服务,mysql、nginx、gchat,并且指定了它们之间的关联关系。

version: '3.7'
services:
  mysql:
    image: mysql:latest
    container_name: mysql
    restart: always
    ports:
      - "3407:3306"
    volumes:
      - ./mysql/data/:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      - ./mysql/sec:/var/lib/mysql-files
    environment:
      MYSQL_ROOT_PASSWORD: "root"
  gchat:
    image: com.demo/gchat:1.0-SNAPSHOT
    container_name: gchat
    restart: always
    ports:
      - "8087:8082"
    depends_on:
      - mysql
    environment:
      jdbc.type: "mysql"
      jdbc.username: "root"
      jdbc.password: "root"
      jdbc.driver: "com.mysql.cj.jdbc.Driver"
      jdbc.url: "jdbc:mysql://mysql:3306/gchat?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"
  nginx:
    image: nginx:1.17.8
    container_name: nginx
    restart: always
    depends_on:
      - gchat
    volumes:
      - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/html:/usr/share/nginx/html
      - ./nginx/logs:/var/log/nginx
    ports:
      - 80:80
    environment:
      - TZ=Asia/Shanghai

这里 mysql 容器的配置文件和数据被挂载到宿主机上,nginx 的配置文件也被挂载到了宿主机上,这样即使删除容器的话,数据也不会丢失;修改配置文件可直接在宿主机上进行编辑,无需通过 docker exec 命令进入容器内修改(或者是通过 docker cp 来 copy 文件至宿主机内)。

执行 docker-compose -p gchat up -d 命令来创建和启动容器,此命令默认会在当前目录下查找 docker-compose.yml 文件,也可手动指定文件位置 -f /opt/gchat/docker-compose.yml ,先看下输出信息:

$ docker-compose -p gchat up -d
Creating network "gchat_default" with the default driver
Creating mysql ... done
Creating gchat ... done
Creating nginx ... done

默认的网络模式为 network_mode: bridge 。

首先会创建一个名称为 gc_default 的网络,然后根据配置 依次创建容器 mysql、 gchat、nginx,并且以其容器名称加入 gc_default 网络中。这样 Docker Compose 管理下的容器之间的相互访问即可通过容器名称加容器端口的方式。

也可以通过 docker network create 命令先创建网络,然后在 yml 中进行配置。

docker network create -d bridge self-network
networks:
  default:
    external:
      name: self-network

通过 docker network ls 查看当前的网络:

/opt/gchat$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
10b2aaa3c026        bridge              bridge              local
c5555d99ae9d        gchat_default       bridge              local
b6a883741497        host                host                local
0f969b2af1da        none                null                local

再查看下刚刚创建的网络 gchat_default 的具体信息:docker network inspect gchat_default

$ docker network inspect gchat_default
......
"Name": "gchat_default",
"Driver": "bridge",
"IPAM": {
    "Driver": "default",
    "Config": [
        {
            "Subnet": "172.27.0.0/16",
            "Gateway": "172.27.0.1"
        }
    ]
},
"Containers": {
    "4e2eacd13160d9d5a98da97e61e5686418d6dd4f8592fef5f64c0ee622307d82": {
        "Name": "gchat",
        "MacAddress": "02:42:ac:1b:00:03",
        "IPv4Address": "172.27.0.3/16"
    },
    "6ff30a833674c4bf2629329d7a63e8b2070c8ea738b3e38c48ae5535addc4d43": {
        "Name": "nginx",
        "MacAddress": "02:42:ac:1b:00:04",
        "IPv4Address": "172.27.0.4/16"
    },
    "d530fef73b38301a9b94421ec213c274129b01f494138786ab4175a8d65f4037": {
        "Name": "mysql",
        "MacAddress": "02:42:ac:1b:00:02",
        "IPv4Address": "172.27.0.2/16"
    }
},
......

信息很清晰,默认的网络驱动是:bridge,网络名称为:gchat_default,网段为 172.27.0.0/16,给每一个容器都分配了一个 IP。

在用户自己定义的 Docker 网络中,容器名称的 DNS 解析会自动发生,Docker 内嵌的 DNS 服务维护容器名称及其 IP 地址,如容器正在使用定义的 Docker 网络,无需执行任何操作,它们可以使用主机名自动找到对方。如下:ping 其它的容器名称

$ docker exec -it gchat ping mysql
PING mysql (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.050 ms
64 bytes from 172.27.0.2: seq=1 ttl=64 time=0.102 ms

$ docker exec -it gchat ping nginx
PING nginx (172.27.0.4): 56 data bytes
64 bytes from 172.27.0.4: seq=0 ttl=64 time=0.045 ms
64 bytes from 172.27.0.4: seq=1 ttl=64 time=0.060 ms

在 Docker 中,容器的主机名默认为容器的 ID,也可以通过 --hostname 参数来指定,通过 docker exec 查看容器的 hosts 文件:

$ docker exec -it mysql cat /etc/hosts
172.27.0.2  d530fef73b38

查看正在运行的容器:

$ docker ps
CONTAINER ID   IMAGE        COMMAND                  STATUS          PORTS                      NAMES
6ff30a833674   nginx:1.17.8  "nginx -g "             Up 19 minutes   80->80/tcp   nginx
4e2eacd13160   gchat:1.0     "/bin/sh -c 'java -c…"  Up 19 minutes   8080/tcp, 8087->8082/tcp   gchat
d530fef73b38   mysql:latest  "docker-entrypoint.s…"  Up 19 minutes   33060/tcp, 3407->3306/tcp  mysql

对于容器内的 DNS 配置,如果宿主机的 /etc/resolv.conf 内容发生改变,Docker 进程会监听到这些改变,并将变化同步至容器的 /etc/resolv.conf 。但前提是,只有在容器停止时,才会同步这些配置的更改。因此,要想使宿主机上配置的 DNS 生效,就需要停止容器后重新启动。

执行 docker inspect gchat 查看容器如下信息:

# system
"ResolvConfPath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/hostname",
"HostsPath": "/var/lib/docker/containers/de88cfcfcb410dba67b4bcb7da/hosts",

网络信息:

"Networks": {
    "gchat_default": {
        "Aliases": [
            "gchat",
            "de88cfcfcb41"
        ],
        "NetworkID": "7a140855e53ec5d86af3733dc7b0ef10ed95437811623eb1d00f6185b7cfcaf8",
        "Gateway": "172.30.0.1",
        "IPAddress": "172.30.0.3",
        "MacAddress": "02:42:ac:1e:00:03",
    }
}

数据卷信息:

# Volumn
"Mounts": [
    {
        "Type": "bind",
        "Source": "/opt/gchat/mysql/data",
        "Destination": "/var/lib/mysql",
        "Mode": "rw", "RW": true,
        "Propagation": "rprivate"
    },
    {
        "Type": "bind",
        "Source": "/opt/gchat/mysql/my.cnf",
        "Destination": "/etc/mysql/my.cnf",
        "Mode": "rw", "RW": true,
        "Propagation": "rprivate"
    }
]

查看日志的话,可通过 docker logs -f gchat,也可通过 docker-compose logs -f gchat 来查看。

如果想要强制重建某个容器,可使用 --force-recreate 参数:

docker-compose up -d --force-recreate mysql

否则只会在容器配置有更改时才会重建容器,容器之间根据 depends_on 参数设置了依赖关系,代表了其创建启动的顺序。重建某个容器时,会先重建其依赖的容器,例如重建 gchat 容器时:

$ docker-compose up -d --force-recreate gchat
Recreating mysql ... done
Recreating gchat ... done

停止并删除所有容器命令:

docker-compose down

删除某个容器,默认只能删除已停止的容器,-f 强制删除:

docker rm -f nginx

磁盘空间使用分析:docker system df

空间清理 docker system prune,此命令会删除:

  1. 所有已停止的容器
  2. 所有不被任何容器使用的 network
  3. 所有悬空镜像,即未被任何容器引用的镜像

这里要注意区分主机端口和容器端口,例如对于上面定义的 mysql 容器,3407 是主机端口,3306 是容器端口,网络化的容器服务之间的通信使用容器端口,例如 gchat 连接 mysql 数据库使用的是 mysql:3306;而对于外部网络访问则需要使用主机端口,例如在其他电脑中通过 Navicat 连接 mysql 则需要使用 3407 端口。

此外,docker 也提供了一些查看容器资源统计信息的命令。

通过 docker stats 查看容器 cpu、mem 使用情况, MEM USAGE / LIMIT 容器使用的总内存和允许使用的总内存,未做限制时,允许使用的量为宿主机总内存。

$ docker stats
CONTAINER ID  NAME    CPU %    MEM USAGE / LIMIT     MEM %   NET I/O          BLOCK I/O        PIDS
93a546af2006  nginx   0.00%    108.5MiB / 4.837GiB   2.19%   4.18kB / 0B      4.76MB / 0B      5
f3b50c9fcb00  gchat   1.80%    437.3MiB / 4.837GiB   8.83%   27kB / 21.7kB    60.3MB / 0B      32
64090ff0d7b0  mysql   0.46%    395MiB / 4.837GiB     7.98%   28.8kB / 20.3kB  72.1MB / 18.8MB  40

查看容器在宿主机中的进程号 docker top [containerId or Name]:

$ docker top f3b50c9fcb00
UID      PID    PPID   C   STIME   TTY    TIME       CMD
root     4001   3975   6   15:21    ?     00:00:12   java -cp /opt/gchat -Xms1024m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m org.springframework.boot.loader.WarLauncher

下面对 gchat 容器的 cpu、memory 资源进行限制,不同版本写法略有差别,具体参看官方说明:

https://docs.docker.com/compose/compose-file/#resources

deploy:
  resources:
    limits:
      cpus: "0.20"
      memory: 2G  

添加如上资源限制标签后,这时通过 docker-compose up -d --force-recreate gchat 重建容器时,会有如下提示,设置的资源限制 deploy 属性被忽略,未起作用。

WARNING: Some services (gchat ) use the ‘deploy’ key, which will be ignored. 
Compose does not support ‘deploy’ configuration - use docker stack deploy to deploy to a swarm.

原因是由于做了资源限制, 并且没有使用 swarm,所以要加上 --compatibility 参数,它会将 version: 3.x 版本设置资源限制的方法转换回 version: 2.x 兼容的属性。

docker-compose --compatibility up -d --force-recreate gchat

# 参数含义
--compatibility If set, Compose will attempt to convert keys in v3 files to their non-Swarm equivalent

可以通过运行 docker-compose --compatibility config 来验证配置,会看到资源限制属性被翻译成 cpus 和 mem_limit。

$ docker-compose --compatibility config
......
services:
  gchat:
    container_name: gchat
    cpus: 0.2
    mem_limit: 2G
    depends_on:
      mysql:
        condition: service_started
  ......
version: '2.3'

Docker Compose 配置中除了指定镜像名称外,还可以指定 Dockerfile 文件,启动时会先根据 yml 中 Dockerfile 的配置来创建镜像,详情参看:

https://docs.docker.com/compose/compose-file/#build

~ END ~

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容