• docker-swarm使用

# 设置"live-restore": false
cat /nix/store/8hghs52v46dhvbgfm3l1dgs6n39cdqi1-daemon.json
{
  "group": "docker",
  "hosts": [
    "0.0.0.0:39012",
    "fd://"
  ],
  "live-restore": false,
  "log-driver": "journald"
}

# nix
virtualisation.docker.enable = true;
virtualisation.docker.enableOnBoot = true;
virtualisation.docker.daemon.settings = {
   hosts=[
    "0.0.0.0:39012"
  ];
  live-restore=false;
};
  • 初始化

# 端口占用
TCP 2377: 用于管理通信(如节点加入和更新)。
TCP  UDP 7946: 用于节点之间的通信。
UDP 4789: 用于覆盖网络(overlay network)通信。

# 初始话内网ip节点
docker swarm init --advertise-addr 116.204.106.129
# Swarm initialized: current node (qxlwqzkkhecvepwujl61na1no) is now a manager.

# To add a worker to this swarm, run the following command:

#     docker swarm join --token SWMTKN-1-16hil64vsxjtj87vlkmd5znncdjoptkzf7x8d7not4qirsvwyt-d3bzjmc8p19a0ux8iqb7zbc5v 116.204.106.129:2377

# To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

# 离开(服务全部都会清除),之后可以重新init
docker swarm leave --force

# 查看当前主节点join token,提供给其他节点加入, 注意ip以实际为准(如果ip和实际不一致会导致管理异常, 可能需要leave force)
docker swarm join-token worker
  • Deploy 通过stack使用compose-file进行部署,而不用安装docker-compose

docker stack ls
# NAME      SERVICES   ORCHESTRATOR
# 从文件创建 https://docs.docker.com/engine/reference/commandline/stack/
# v3详细文档: https://docs.docker.com/compose/compose-file/compose-file-v3/
# The deploy command supports compose file version 3.0 and above.
docker stack deploy --compose-file dep.yaml exadmin
# Creating network exadmin_default
# Creating service exadmin_exadmin

# dep.yaml这里的ports会直接映射到实体机,在物理机器访问
curl http://127.0.0.1:8080


# ps
docker stack ps exadmin
# 显示Running/和Shutdown 数据以及 \_开头删除的数据

# 删除
docker stack rm exadmin
# Removing service exadmin_exadmin
# Removing network exadmin_default

docker service ls
# ID             NAME              MODE         REPLICAS   IMAGE                                               PORTS
# cyqmyd3ipiuy   exadmin_exadmin   replicated   2/2        registry.jihulab.com/jcleng/ex-admindemo:aa344af0   *:8080->8080/tcp
# https://docs.docker.com/engine/reference/commandline/stack_services/

docker stack services exadmin
# ID             NAME              MODE         REPLICAS   IMAGE                                               PORTS
# cyqmyd3ipiuy   exadmin_exadmin   replicated   4/4        registry.jihulab.com/jcleng/ex-admindemo:aa344af0   *:8080->8080/tcp


# 设置数量,查看 docker stack ps exadmin
docker service update --replicas 2 exadmin_exadmin
# --health-cmd=命令,用于检查接口的命令。
# --health-interval=时间间隔 (默认: 30s),它是每次执行healthcheck的时间间隔。
# --health-timeout=时间间隔 (默认: 30s),如果在超时时间之内没有响应,则代表异常。
# --health-retries=N (默认: 3),连续达到多少次异常之后退出。
# --health-start-period=时间间隔 (默认:0),容器启动之后多久进行健康检查(服务启动预热),即运行health-cmd。
# 健康检查实例: https://github.com/docker-library/healthcheck
# 如果容器中没有curl命令,可以下载httpie来使用https://github.com/httpie/httpie/releases
# curl 参数用-f/--fail,httpie用--check-status
# wget用(检查文件是不是存在)wget --no-verbose --tries=1 --spider http://localhost:2019/metrics
# 注意需要容器存在的命令,否则inspect容器会提示: /bin/sh: 1: curl: not found
docker service update \
  --health-cmd "/srv/http --check-status http://127.0.0.1:8080 || exit 1" \
  --health-interval 5s \
  --health-timeout 3s \
  --health-retries 3 \
  --health-start-period 45s \
  --image registry.jihulab.com/jcleng/ex-admindemo:9699d0ba \
  exadmin_exadmin
# docker ps 的时候状态会增加 (healthy) 显示

# 查看服务
docker service inspect exadmin_exadmin
  • stack部署之后可以查看服务

# 节点
docker node ls
# ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
# qxlwqzkkhecvepwujl61na1no *   nixos      Ready     Active         Leader           20.10.18

# 服务
docker service ls
# ID        NAME      MODE      REPLICAS   IMAGE     PORTS
  • 不使用stack,直接创建服务

# https://docs.docker.com/engine/reference/commandline/service_create/
docker service create --name admindemo_sv \
--replicas=3 \
-p 8088:8080 \
registry.jihulab.com/jcleng/ex-admindemo:aa344af0
# 查看,且8088进行访问
docker service ls
# ID             NAME              MODE         REPLICAS   IMAGE                                               PORTS
# su6y8prthnzu   admindemo_sv      replicated   3/3        registry.jihulab.com/jcleng/ex-admindemo:aa344af0   *:8088->8080/tcp

# 查看service错误日志
docker service ps admindemo_sv
docker service logs 16oikw3t8f0c
  • dep.yaml 文档 https://docs.docker.com/compose/compose-file/deploy/

version: '3.3'
services:
  exadmin:
    image: registry.jihulab.com/jcleng/ex-admindemo:aa344af0
    ports:
      - "8080:8080"
    deploy:
      replicas: 4
      update_config:
        parallelism: 2
        failure_action: rollback
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
# 更新
# docker service update --image registry.jihulab.com/jcleng/ex-admindemo:bfee2a3a exadmin_exadmin --with-registry-auth
# 因为有4个副本,parallelism设置同时更新2个。先更新两个,等待delay后在更新两个
  • api 文档 https://docs.docker.com/engine/api/v1.41/#section/Versioning

curl -X GET http://127.0.0.1:39012/version
curl -X GET http://127.0.0.1:39012/images/json?all=false
curl -X GET http://127.0.0.1:39012/v1.41/containers/json

# 私有仓库[更新镜像]需要请求头加上验证信息,就是base64_encode的json帐户授权信息
X-Registry-Auth: "xxxxxxxxxx"

<?php
$json = <<<JSON
{
  "username": "jcleng",
  "password": "password123456",
  "email": "[email protected]",
  "serveraddress": "registry.jihulab.com"
}
JSON;
var_export(base64_encode(json_encode(json_decode($json, true))));
# 文档: https://docs.docker.com/registry/
# https://distribution.github.io/distribution/
# 使用官方的registry镜像,映射到本地的5555端口,注意公网的5555端口不要开放出来
docker pull registry
docker run -v ~/registry:/var/lib/registry -itd -p 5000:5000 --name registry registry
# 设置Auth授权验证
https://distribution.github.io/distribution/about/deploying/#native-basic-auth
## 创建用户密码
docker run -itd \
  --restart unless-stopped \
  -v ./auth/:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -p 5000:5000 \
  --name registry \
  registry.cn-hangzhou.aliyuncs.com/jcleng/library-registry:3.0

# 新增用户和密码
htpasswd -Bb ./auth/htpasswd test test
# 登录
docker login --username=test -p test localhost:5000
# 查看状态
curl http://192.168.195.35:5000/v2/_catalog

# 配置自己的域名解析到公网服务器的内网ip,就可以使用5555端口
ndocker.leng2011.icu 解析到 192.168.0.7
# 配置ssl
ndocker.leng2011.icu:443 {
  reverse_proxy * {
    to http://127.0.0.1:5000
  }
  tls /home/jcleng/cert/ndocker.leng2011.icu_nginx/ndocker.leng2011.icu_bundle.crt /home/jcleng/cert/ndocker.leng2011.icu_nginx/ndocker.leng2011.icu.key
}

# 在公网服务器上进行测试,测试用已经存在的镜像增加一个tag
docker tag 06541a2a33fb ndocker.leng2011.icu/jcleng/ntfy
docker images|grep ntfy
# binwiederhier/ntfy                                                  latest                    06541a2a33fb   2 months ago   27MB
# ndocker.leng2011.icu/jcleng/ntfy                                    latest                    06541a2a33fb   2 months ago   27MB

# 进行推送即可
docker push ndocker.leng2011.icu/jcleng/ntfy:latest
# 获取,内网是很快的
docker rmi ndocker.leng2011.icu/jcleng/ntfy:latest
docker pull ndocker.leng2011.icu/jcleng/ntfy:latest
# 镜像列表
## 文件查看
tree -L 2 ~/imagedata/docker/registry/v2/repositories
## api,获取用户和镜像,然后获取tag
curl https://ndocker.leng2011.icu/v2/_catalog
curl https://ndocker.leng2011.icu/v2/jcleng/ntfy/tags/list

# 删除,获取config的digest: https://github.com/distribution/distribution/blob/main/docs/spec/api.md#deleting-an-image

# 手动删除imagedata/docker/registry/v2/repositories的目录,文件在blobs目录里面
# 执行命令,清除blobs的数据
registry garbage-collect /etc/docker/registry/config.yml

# 比如自己的docker-runner就可以开设到本内网域名,无需登录即可上传

# 配置文件,可以配置密码等: https://docs.docker.com/registry/configuration/#auth
/etc/docker/registry/config.yml

# 使用htpasswd作为密码,加密方式是bcrypt https://docs.docker.com/registry/configuration/#htpasswd
# nix-shell -p apacheHttpd
# htpasswd -Bc htpasswd2 jcleng
# 用123456测试
# cat htpasswd2
# jcleng:$2y$05$8UMyFaiuS299X/mBZ2InA.nAn.Ni0QgV.QDrrjyGl4toOF/FQ7b0a

auth:
  htpasswd:
    realm: basic-realm
    path: /var/lib/registry/docker/registry/htpasswd2

# 配合web端简易管理(不推荐),删除操作等,但是不支持内网操作,只是html静态页面
https://github.com/Joxit/docker-registry-ui


# gitlab的runner使用
- docker build --pull -t "ndocker.leng2011.icu/$CI_PROJECT_PATH_SLUG${tag}" .
- docker push "ndocker.leng2011.icu/$CI_PROJECT_PATH_SLUG${tag}"
# 项目地址: https://jihulab.com/jcleng1/first_demo/
# 生成的容器名称,$CI_PROJECT_PATH_SLUG就是项目地址,tag用$CI_COMMIT_REF_SLUG或者$CI_COMMIT_SHORT_SHA
jcleng1-first-demo:v21
# 安装器,记得先打开Docker Swarm
# 执行命令会初始化安装管理面板引导程序
docker run -it --rm \
  --name swarmpit-installer \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  swarmpit/install:1.9

# 或者手动安装
git clone --depth=1 http://github.com/swarmpit/swarmpit -b master
docker stack deploy -c swarmpit/docker-compose.yml swarmpit
# 初始密码是12345678


# 可能会提示失败,查看实际服务状态
docker service ls|grep swarmpit
# bcpsiqw2vz2z   swarmpit_agent      global       1/1        swarmpit/agent:2.2
# pvo9njyuoi65   swarmpit_app        replicated   1/1        swarmpit/swarmpit:1.9                          *:888->8080/tcp
# anrv0itajrur   swarmpit_db         replicated   1/1        couchdb:2.3.0
# 4pla8l9ihc8d   swarmpit_influxdb   replicated   1/1        influxdb:1.7
# 全部启动之后,访问端口即可
http://www.leng2011.icu:888/
# 配置Registry v2仓库地址的时候,不需要选[Use custom API]


# 其他面板
https://github.com/cuigh/swirl
  • 例子

version: '3.9'
services:
  myingsite:
    image: ndocker.leng2011.icu/jcleng-imgsite:52ce37b8
    ports:
      - "7871:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080"]
      interval: 5s
      timeout: 6s
      retries: 3
      start_period: 40s
    deploy:
      replicas: 2
      update_config:
        parallelism: 1
        delay: 30s
        failure_action: rollback
        monitor: 15s
        max_failure_ratio: 0
        order: start-first
      rollback_config:
        parallelism: 1
        delay: 30s
        failure_action: pause
        monitor: 15s
        max_failure_ratio: 0
        order: start-first
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
# 使用3.9支持update_config/order
# docker stack deploy --compose-file dep.yaml mainsite
# Creating network mainsite_default
# Creating service mainsite_myingsite

# docker service rm mainsite_myingsite
# docker network rm mainsite_default
  • 使用docker的socket文件进行调用api

sudo chmod 777 /var/run/docker.sock

curl --unix-socket /var/run/docker.sock http://localhost/version | jq
curl --unix-socket /var/run/docker.sock http://localhost/services/nginxs_nginx | jq
curl --unix-socket /var/run/docker.sock http://localhost/tasks | jq
curl --unix-socket /var/run/docker.sock http://localhost/v1.51/containers/json?filters=%7B%22health%22%3A%5B%22healthy%22%5D%2C%22label%22%3A%20%5B%22openresty.enable%3Dtrue%22%5D%7D | jq
  • 主节点配置私有仓库

// cat ~/.docker/config.json
// auth的值是base64_encode("email:password");名称是域名

{
  "auths": {
    "registry.cn-hangzhou.aliyuncs.com": {
      "auth": "ai5jLmxlbxxxxxxxxxxxxxxxxEyMzQ1Xg=="
    }
  }
}

// 创建服务时, 子节点需要带上X-Registry-Auth才能拉取镜像
  • 高可用, 使用多个Leader节点, 然后配置上有负载均衡器到各个主节点

# 如果是单节点使用, 可以直接使用nginx(ssl)+work节点作为服务直接使用swarm进行流量分发(内部网络使用服务商提供的内网, 可能是不可靠的)
# 如果多节点高可用, 需要使用自己的组网工具组网(ztncui自建作为参看), 然后上层再使用负载均衡(ssl)再进行流量分发到多个主节点ip


# 当一个主节点Leader宕机, 可以切换到其他Leader节点进行管理

# 主节点, 获取manager token
docker swarm join-token manager
# 新节点执行join
docker node ls
# ID                            HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
# 0a0s2aj5co77qczb9xkwinflv *   0822c3de9560   Ready     Active         Leader           28.2.2
# imkg3c2t85bon75tdwt9pzpq6     f42e42c32252   Ready     Active         Reachable        28.2.2

# 或者, 主节点给work节点提升回管理节点角色
docker swarm join-token worker

# 查看当前节点名称
docker info|grep -C 2 NodeID
docker node promote tsel91769bax7l4efubrlrzy2
docker node ls
# ID                            HOSTNAME       STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
# tsel91769bax7l4efubrlrzy2     4c020a54e77f   Ready     Active         Reachable        28.2.2
# 0a0s2aj5co77qczb9xkwinflv *   0822c3de9560   Ready     Active         Leader           28.2.2
# imkg3c2t85bon75tdwt9pzpq6     f42e42c32252   Ready     Active         Reachable        28.2.2


# The swarm does not have a leader.
# 主节点全部异常, 找一个可以运行的主节点, 执行初始化重新作为主节点
docker swarm init --force-new-cluster
# 再删除宕机的节点
docker node rm xzswjzcvhj5n9febhvr4xn71c