月度归档:2018年03月

从锦囊妙计想到的03–线程介绍

前面 从锦囊妙计想到的01   从锦囊妙计想到的02

介绍了 计算机就是一个执行任务的“人”, 这些人物就是一个个的锦囊(指令)。 这些各种各样的指令混合到一起后形成程序, 为了清晰明确的表明程序绘制了程序的流程图。

本文讨论一下, 什么情况下 曹军会获胜, 什么情况下曹军会失败(这里仅仅是 为说明程序上的一些事情而 杜撰的一下结论和事情, 千万别当真!!)。

首先, 若是诸葛亮亲自指挥大军, 对抗曹军, 那么在什么情况下, 都是曹军失败。

其次, 若是关羽指挥 大军对抗曹军,   需要看曹军是什么人员领军, 若是曹操亲自领军, 估计关羽获胜几率非常低。 若是其他大将领军, 关羽获胜的可能性很大

 因此可以看到, 战斗的最终结果只有到这些因素都最终确定了 才能最终确定。 那么什么时候才能真正确定这些结果呢??

我们可以通过下面图形思考一下!

j9

从上面的图中, 可以了解到, 有两个重要的时间点,

第一个时间点, 是获知曹军要来, 然后商讨行动计划的时刻, 在这个时刻有大量的 不确定的 情况, 因此行动计划必须  具有能根据不同情况而变化的能力, 这个就是那个判断的分支。

第二个时间点, 是曹军真正来临了, 两军在城外对战了, 这个时候, 一切不确定因素都确定了, 因此这个时候程序一定沿着一个情况(一个分支)进行下去。

可以在进一步整理一下, 就如下图, 能更清晰些。

j9-2

 

通过上面 两幅图, 要重点说明的是:

  • 程序的编写是    想象中的事情....  因此一定存在各种各样的不确定的地方, 因此 要把这些都考虑进去(因此自然会有很多不同情况的分支供将来选择), 这样在 实际执行时, 会根据当时的具体情况执行特定的功能。
  • 程序的执行是   实际中(现实中)的事情, 这个时刻 全部的  不确定因素一定都确定了, 否则程序没办法在各个分支中寻找一个,然后执行。

下我们看另外一幅图

j9-3

 

这幅图是, 程序实际执行过程中的一个 具体的工作流程。

这个图可以进一步优化为:

j

其实, 无论多么复杂的  一个程序流程(或者程序), 最后都 可以抽象出一个, 上面简化的执行路线图。 通过上图可以知道

  • 程序是一个执行路线, 没有分支(具体的,时间的执行时)
  • 执行过程是 从上到下,一个路线向前进行, 没有后退
  • 程序执行路线 是有开始 和结束的, 结束后就不在进行了!

这条具体的执行路线, 通常称为线程(thread)。  通俗一点的解释, 就是一条沿着一个路线执行的程序, 通常可以成为线程(这个不是准确的叫法, 这里为了小朋友能理解, 尽量采用了通俗的近似, 随着时间的推移, 程序理解的增多, 可以慢慢理解这些概念)。

下面是对程序的另外一个理解方式

jjj

 

从上图,

  • 一个编写好的程序(就是一堆锦囊), 是一个程序, 这个时候程序还没开始执行。
  • 把编写好的程序拿来执行, 在进行执行过程中的程序 是一个进程
  • 在一个进程中(一个进行中的一堆锦囊), 必然有一个执行路线,这个路线是线程。
  • 一个进程中必要有一个线程, 但是也可以有若干条其他执行路线, 后面我们会讨论的
  • 另外,一个程序可以被多次执行, 也可以被同时多次执行, 可见通过一个程序可以创建若干个进程的。

 

本文重点:

1. 编程的时间是  程序执行前, 因此都是预期的(就是不能确定将来真正执行时, 到底要准确执行那个分支或者过程等等),不是真正的!

2. 程序在执行时,一切没有确定的事情都确定了, 因此走那个分支, 那个循环如何走, 就确定了

3. 程序执行是需要一定时间的, 因此程序在执行进行中,  叫做一个进程

4. 线程是 进程中,  一系列锦囊操作的过程,这些过程可以被一条线串起来,并且在执行过程中不确定的事情都确定了, 这个执行路线是可以度量的, 因此把这些 可以用线串连起来的 过程叫做线程!

 

相关文章

计算机介绍                                  从锦囊妙计想到的01

流程图(分支结构)介绍          从锦囊妙计想到的02

线程介绍                                     从锦囊妙计想到的03

循环结构介绍                             从锦囊妙计想到的05

流程线程总结                             从锦囊妙计想到的06

cpu和线程定义、开始               从锦囊妙计想到的07

分布式计算                                  从锦囊妙计想到的08

分布式中事件和计数                 从锦囊妙计想到的09

内容总结                                     从锦囊妙计想到的10

数据类型,变量简介                从锦囊妙计想到的11

函数和参数                                从锦囊妙计想到的12

用户交互与数据输入输出       从锦囊妙计想到的13

人机交互界面                            从锦囊妙计想到的15 

过程与对象                                从锦囊妙计想到的16

同步和异步                                从锦囊妙计想到的17

顺序打印                                    从锦囊妙计想到的18

数据输入输出                            从锦囊妙计想到的19

屏幕坐标和打印                        从锦囊妙计想到的20

java函数控制输出                     从锦囊妙计想到的21

逐步细化解决复杂问题           从锦囊妙计想到的22

java入门                                    从锦囊妙计想到的23

java复杂过程分析                   从锦囊妙计想到的25

中间辅助功能解决问题          从锦囊妙计想到的26

叠加操作输出复杂图形          从锦囊妙计想到的27

时间和空间                               从锦囊妙计想到的28

编写边测解决问题                  从锦囊妙计想到的29

让程序动起来                          从锦囊妙计想到的30

程序往复运动                           从锦囊妙计想到的31

Docker可视化与管理工具

Preface

在学习了Docker的基本操作之后,接下来就是Docker的管理部分了,这包括Docker的可视化管理以及集群管理。

此篇主要记录Docker私有库的搭建,Docker编排工具的介绍以及使用,可视化管理工具的介绍以及搭建…

 

Docker Registry & Mirror

Harbor

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源Docker Distribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry中, 确保数据和知识产权在公司内部网络中管控。另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。

  • 基于角色的访问控制 - 用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。
  • 镜像复制 - 镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。
  • 图形化用户界面 - 用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。
  • AD/LDAP 支持 - Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。
  • 审计管理 - 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
  • 国际化 - 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。
  • RESTful API - RESTful API 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。
  • 部署简单 - 提供在线和离线两种安装工具, 也可以安装到vSphere平台(OVA方式)虚拟设备。
  • 集成clair进行镜像安全漏洞扫描

Harbor共由七个容器组成:

a.harbor-adminserver:harbor系统管理服务

b.harbor-db: 由官方mysql镜像构成的数据库容器

c.harbor-jobservice:harbor的任务管理服务

d.harbor-log:harbor的日志收集、管理服务

e.harbor-ui:harbor的web页面服务

f.nginx:负责流量转发和安全验证

g.registry:官方的Docker registry,负责保存镜像

Condition

前置条件:

1.需要Python2.7或以上

2.Docker版本要在1.10或以上

3.Docker compose版本要在1.6.0或以上

Download

Release页面下载离线安装包(或在线也可以,不过安装的时候很慢)

Config

解压缩之后,目录下会生成harbor.conf文件,该文件就是Harbor的配置文件。

# 1. hostname设置访问地址,可以使用ip、域名,不可以设置为127.0.0.1或localhost
# 2. 默认情况下,harbor使用的端口是80,若使用自定义的端口,除了要改docker-compose.yml文件中的配置外,
# 这里的hostname也要加上自定义的端口,在docker login、push时会报错
# hostname = ${IP_ADDR}:${PORT}
hostname = 192.168.1.102:8888
# 访问协议,默认是http,也可以设置https,如果设置https,则nginx ssl需要设置on
ui_url_protocol = http
# mysql数据库root用户默认密码root123,实际使用时修改下
db_password = root123
#Maximum number of job workers in job service 
max_job_workers = 3
#The path of secretkey storage
secretkey_path = /data
# 启动Harbor后,管理员UI登录的密码,默认是Harbor12345
# 若修改了此处的admin登录密码。则登录后台时使用修改后的密码
harbor_admin_password = Harbor12345
# 认证方式,这里支持多种认证方式,如LADP、本次存储、数据库认证。默认是db_auth,mysql数据库认证
auth_mode = db_auth
# 是否开启自注册
self_registration = on
# Token有效时间,默认30分钟
token_expiration = 30
# 用户创建项目权限控制,默认是everyone(所有人),也可以设置为adminonly(只能管理员)
project_creation_restriction = everyone

harbor默认监听80端口,我们修改为8888端口,同时docker-compose.yml也需要修改proxy的端口

还可以修改仓库的存储位置:

Install

运行安装脚本:

./install.sh

集成clair漏洞扫描:

./install.sh --with-clair

脚本会自动解压镜像文件并运行docker-compose

或者运行prepare文件再手动运行docker-compose

启动之后浏览器打开刚才修改的hostname

帐号密码默认是 admin/Harbor12345,可在配置文件harbor.conf中修改

修改配置文件之后需要重新生成一些内置配置:

./prepare
docker-compose up -d

登录被refuse

多次docker login被refuse

这是因为 Docker 默认不允许非 HTTPS 方式推送镜像。我们可以通过 Docker 配置来取消这个限制,或者配置能够通过 HTTPS 访问的私有仓库。

有两种方式达到效果

方案一

首先修改/etc/default/docker

DOCKER_OPTS="--insecure-registry 192.168.1.102:8888"

修改/lib/systemd/system/docker.service

# 找到ExecStart=/usr/bin/dockerd -H fd:// 
# 前面添加EnvironmentFile=-/etc/default/docker,后面追加$DOCKER_OPTS

EnvironmentFile=-/etc/default/docker
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_OPTS

重启docker:

sudo systemctl daemon-reload && sudo systemctl restart docker

方案二

如果是systemd 的系统例如Ubuntu16.04+Debian 8+centos 7,可以在/etc/docker/daemon.json 中写入如下内容:

{
  "registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.1.102:8888"]
}

然后重启docker:

sudo systemctl daemon-reload && sudo systemctl restart docker

centos下是这样的

修改/etc/sysconfig/docker:

# OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false -H'后面追加 --insecure-registry 10.0.11.150:5000

OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false -H --insecure-registry 10.0.11.150:5000'
重启:

sudo systemctl restart docker

 

Login and Push

docker login 192.168.1.102:8888 -u admin -p Harbor12345

docker tag ubuntu:latest 192.168.1.102/library/ubuntu:latest
docker push 192.168.1.102/library/ubuntu:latest

注意:使用docker stack deploy时,如果是私有镜像,需要终端登录后加上--with-registry-auth选项。

删除Harbor

删除harbor,但保留数据

docker-compose down -v

删除harbor数据(对应docker-compose.yml里面的数据卷)

rm -r /data/database
rm -r /data/registry

删除镜像

 

UI界面操作删除镜像,只是删除元数据,并未删除真实数据,还需要调用registry的garbage-collect进行清理

docker-compose stop

docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect --dry-run /etc/registry/config.yml #只是打印过程,并不删除

docker run -it --name gc --rm --volumes-from registry vmware/registry:2.6.2-photon garbage-collect /etc/registry/config.yml

docker-compose start
注意:配置文件config.yml挂载在/etc/registry/下.

 

Harbor做Mirror加速器

mirror服务器和私有服务器分开部署,因为mirror服务器只能pull,不能push

./prepare之后修改config/registry/config.yml,在config.yml文件的最后追加以下配置:

proxy:
  remoteurl: https://vioqnt8w.mirror.aliyuncs.com

这样保证docker pull并不存在于docker harbor中的image时,会从Docker Hub上去pull,并缓存于mirror服务器。

最后修改/etc/docker/daemon.json中的"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]

But,试了一下发现木有效果

Registry Mirror

registry mirror原理

Docker Hub的镜像数据分为两部分:index数据和registry数据。前者保存了镜像的一些元数据信息,数据量很小;后者保存了镜像的实际数据,数据量比较大。平时我们使用docker pull命令拉取一个镜像时的过程是:先去index获取镜像的一些元数据,然后再去registry获取镜像数据。

所谓registry mirror就是搭建一个registry,然后将docker hub的registry数据缓存到自己本地的registry。整个过程是:当我们使用docker pull去拉镜像的时候,会先从我们本地的registry mirror去获取镜像数据,如果不存在,registry mirror会先从docker hub的registry拉取数据进行缓存,再传给我们。而且整个过程是流式的,registry mirror并不会等全部缓存完再给我们传,而且边缓存边给客户端传。

对于缓存,我们都知道一致性非常重要。registry mirror与docker官方保持一致的方法是:registry mirror只是缓存了docker hub的registry数据,并不缓存index数据。所以我们pull镜像的时候会先连docker hub的index获取镜像的元数据,如果我们registry mirror里面有该镜像的缓存,且数据与从index处获取到的元数据一致,则从registry mirror拉取;如果我们的registry mirror有该镜像的缓存,但数据与index处获取的元数据不一致,或者根本就没有该镜像的缓存,则先从docker hub的registry缓存或者更新数据。

1、拉取镜像

docker pull registry:latest

2、获取registry的默认配置

docker run -it --rm --entrypoint cat registry:latest  /etc/docker/registry/config.yml > config.yml

内容可能如下:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

我们在最后面加上如下配置:

proxy:
  remoteurl: https://registry-1.docker.io
  username: [username]
  password: [password]

usernamepassword是可选的,如果配置了的话,那registry mirror除了可以缓存所有的公共镜像外,也可以访问这个用户所有的私有镜像。

启动registry容器:

Bash

docker run  --restart=always -p 5000:5000 --name v2-mirror -v /data:/var/lib/registry -v  $PWD/config.yml:/etc/registry/config.yml registry:latest /etc/registry/config.yml

当然我们也可以使用docker-compose启动:

version: '3'
services:
  registry:
    image: library/registry:latest
    container_name: registry-mirror
    restart: always
    volumes:
      - /data:/var/lib/registry
      - ./config.yml:/etc/registry/config.yml
    ports:
      - 5000:5000
    command:
      ["serve", "/etc/registry/config.yml"]

curl验证一下服务是否启动OK:

# ybd @ ybd-PC in ~ [17:30:14] 
$ curl -I http://192.168.6.113:5000
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Fri, 05 Jan 2018 09:30:27 GMT
Content-Type: text/plain; charset=utf-8

最后修改/etc/docker/daemon.json/etc/default/docker中的registry-mirrors即可

Cluster and Orchestrate Tools

Docker Compose

官方文档:https://docs.docker.com/compose/

release:https://github.com/docker/compose/releases

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

Dockerfile 可以让用户管理一个单独的应用容器。使用Docker Compose,不再需要使用shell脚本来启动容器。在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器

Install

在release页面找到最新版安装,ex:

sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

变为可执行命令:

sudo chmod +x /usr/local/bin/docker-compose

检查安装成功:

docker-compose --version

卸载:

sudo rm /usr/local/bin/docker-compose

Command

基本命令:

-p 指定项目名称

build 构建项目中的服务容器 –force-rm 删除构建过程中的临时容器

--no-cache 构建过程中不使用 cache

--pull 始终通过 pull 来获取更新版本的镜像

docker-compose kill 强制停止服务容器

docker-compose logs 查看容器的输出 调试必备

docker-compose pause 暂停一个服务容器

docker-compose unpause 恢复暂停

docker-compose port 打印某个容器端口所映射的公共端口

docker-compose ps 列出项目中目前的所有容器 -q 只打印容器 id

docker-compose pull 拉取服务依赖的镜像

docker-compose restart -t 指定重启前停止容器的超时默认10秒

docker-compose rm 删除所有停止状态的容器先执行 stop

docker-compose run 指定服务上执行一个命令

docker-compose start 启动已经存在的服务容器

docker-compose stop 停止已经存在的服务容器

docker-compose up 自动构建、创建服务、启动服务,关联一系列,运行在前台,ctrl c 就都停止运行。如果容器已经存在,将会尝试停止容器,重新创建。如果不希望重新创建,可以 --no-recreate 就只启动处于停止状态的容器,如果只想重新部署某个服务,可以使用

docker-compose up --no-deps -d ,不影响其所依赖的服务

docker-compose up -d 后台启动运行,生产环境必备

docker-compose down 停止并删除容器

Zsh命令补全

mkdir -p ~/.zsh/completion
curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/zsh/_docker-compose > ~/.zsh/completion/_docker-compose

.zshrc添加:

注意:(如果是oh-my-zsh,在$ZSH/oh-my-zsh.sh中添加)

fpath=(~/.zsh/completion $fpath)

执行:

autoload -Uz compinit && compinit -i

重载:

exec $SHELL -l

Compose 模板文件

默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。

version: "3"
services:
  webapp:
    image: examples/web
    ports:
      - "80:80"
    volumes:
      - "/data"

注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。

如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中再次设置。下面分别介绍各个指令的用法。

build

指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。

version: '3'
services:

  webapp:
    build: ./dir

你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径。

使用 dockerfile 指令指定 Dockerfile 文件名。

使用 arg 指令指定构建镜像时的变量。

version: '3'
services:

  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1

使用 cache_from 指定构建镜像的缓存

build:
  context: .
  cache_from:
    - alpine:latest
    - corp/web_app:3.14

cap_add, cap_drop

指定容器的内核能力(capacity)分配。

例如,让容器拥有所有能力可以指定为:

cap_add:
  - ALL

去掉 NET_ADMIN 能力可以指定为:

cap_drop:
  - NET_ADMIN

command

覆盖容器启动后默认执行的命令。

command: echo "hello world"

configs

仅用于 Swarm mode,详细内容请查看下面Swarm模式介绍

cgroup_parent

指定父 cgroup 组,意味着将继承该组的资源限制。

例如,创建了一个 cgroup 组名称为 cgroups_1

cgroup_parent: cgroups_1

container_name

指定容器名称。默认将会使用 项目名称_服务名称_序号 这样的格式。

container_name: docker-web-container

注意: 指定容器名称后,该服务将无法进行扩展scale),因为 Docker 不允许多个容器具有相同的名称。

deploy

仅用于 Swarm mode,这是 V3 才能使用的语法,通过docker-compose up方式启动会忽略这部分。

语法规则:

deploy:
  replicas: 6
  update_config:
    parallelism: 2
    delay: 10s
  restart_policy:
    condition: on-failure
mode

首先 deploy 提供了一个模式选项,它的值有 global 和 replicated 两个,默认是 replicated 模式。

这两个模式的区别是:

  • global:每个集群每个服务实例启动一个容器,就像以前启动 Service 时一样。
  • replicated:用户可以指定集群中实例的副本数量。

以前这个功能是无法在 Compose 中直接实现的,以前需要用户先使用 docker-compose bundle 命令将 docker-compose.yml 转换为 .dab 文件,然后才能拿到集群部署,而且很多功能用不了。

但是随着这次更新把 stack 加进来了,deploy 也就水到渠成加进了 Compose 功能中。

replicas

上面说到可以指定副本数量,其中 replicas 就是用于指定副本数量的选项。

deploy:
  replicas: 6

部署服务栈:

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

这是 Docker 1.12 版本时就引入的概念,允许用户限制服务容器,下面是官方的说明:

node attributematchesexample
node.idNode IDnode.id==2ivku8v2gvtg4
node.hostnameNode hostnamenode.hostname!=node-2
node.roleNode rolenode.role==manager
node.labelsuser defined node labelsnode.labels.security==high
engine.labelsDocker Engine’s labelsengine.labels.operatingsystem==ubuntu 14.04
version: '3'
services:
  db:
    image: postgres
    deploy:
      placement:
        constraints:
          - node.role == manager
          - engine.labels.operatingsystem == ubuntu 14.04
        preferences:
          - spread: node.labels.zone
update_config

早在上一个版本中,Swarm 就提供了一个升级回滚的功能。当服务升级出现故障时,超过重试次数则停止升级的功能,这也很方便,避免让错误的应用替代现有正常服务。

这个选项用于告诉 Compose 使用怎样的方式升级,以及升级失败后怎样回滚原来的服务。

  • parallelism: 服务中多个容器同时更新。
  • delay: 设置每组容器更新之间的延迟时间。
  • failure_action: 设置更新失败时的动作,可选值有 continue 与 pause (默认是:pause)。
  • monitor: 每次任务更新失败后监视故障的持续时间 (ns|us|ms|s|m|h) (默认:0s)。
  • max_failure_ratio: 更新期间容忍的故障率。
resources

看例子:

resources:
  limits:
    cpus: '0.001'
    memory: 50M
  reservations:
    cpus: '0.0001'
    memory: 20M

知道干啥用了吧,这是一个新的语法选项,替代了之前的类似 cpu_shares, cpu_quota, cpuset, mem_limit, memswap_limit 这种选项。统一起来好看点。

restart_policy

设置如何重启容器,毕竟有时候容器会意外退出。

  • condition:设置重启策略的条件,可选值有 none, on-failure 和 any (默认:any)。
  • delay:在重新启动尝试之间等待多长时间,指定为持续时间(默认值:0)。
  • max_attempts:设置最大的重启尝试次数,默认是永不放弃,哈哈,感受到一股运维的绝望。
  • window:在决定重新启动是否成功之前要等待多长时间,默认是立刻判断,有些容器启动时间比较长,指定一个“窗口期”非常重要。

devices

指定设备映射关系。

devices:
  - "/dev/ttyUSB1:/dev/ttyUSB0"

depends_on

解决容器的依赖、启动先后的问题。以下例子中会先启动 redis db 再启动 web

version: '3'

services:
  web:
    build: .
    depends_on:
      - db
      - redis

  redis:
    image: redis

  db:
    image: postgres

注意:web 服务不会等待 redis db 「完全启动」之后才启动。

dns

自定义 DNS 服务器。可以是一个值,也可以是一个列表。

dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 114.114.114.114

配置 DNS 搜索域。可以是一个值,也可以是一个列表。

dns_search: example.com

dns_search:
  - domain1.example.com
  - domain2.example.com

tmpfs

挂载一个 tmpfs 文件系统到容器。

tmpfs: /run
tmpfs:
  - /run
  - /tmp

env_file

从文件中获取环境变量,可以为单独的文件路径或列表,默认读当前目录.env

如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径

如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准

env_file: .env

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

环境变量文件中每一行必须符合格式,支持 # 开头的注释行。

# common.env: Set development environment
PROG_ENV=development

environment

设置环境变量。你可以使用数组或字典两种格式。

只给定名称的变量会自动获取运行 Compose 主机上对应变量的值可以用来防止泄露不必要的数据

environment:
  RACK_ENV: development
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SESSION_SECRET

如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括

y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF

expose

暴露端口,但不映射到宿主机,只被连接的服务访问。

仅可以指定内部端口为参数

expose:
 - "3000"
 - "8000"

注意:不建议使用该指令。

链接到 docker-compose.yml 外部的容器,甚至并非 Compose 管理的外部容器。

external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql

extra_hosts

类似 Docker 中的 --add-host 参数,指定额外的 host 名称映射信息。

extra_hosts:
 - "googledns:8.8.8.8"
 - "dockerhub:52.1.157.61"

会在启动后的服务容器中 /etc/hosts 文件中添加如下两条条目。

8.8.8.8 googledns
52.1.157.61 dockerhub

healthcheck

通过命令检查容器是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3

image

指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉去这个镜像。

image: ubuntu
image: orchardup/postgresql
image: a4bc65fd

labels

为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息。

labels:
  com.startupteam.description: "webapp for a startup team"
  com.startupteam.department: "devops department"
  com.startupteam.release: "rc3 for v1.0"

注意:不推荐使用该指令。

logging

配置日志选项。

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

目前支持三种日志驱动类型。

driver: "json-file"
driver: "syslog"
driver: "none"

options 配置日志驱动的相关参数。

options:
  max-size: "200k"
  max-file: "10"

更多详情:https://docs.docker.com/engine/admin/logging/overview/

network_mode

设置网络模式。使用和 docker run--network 参数一样的值。

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

配置容器连接的网络。

version: "3"
services:

  some-service:
    networks:
     - some-network
     - other-network

networks:
  some-network:
  other-network:

Docker 网络类型,有 bridge overlay,默认为bridge。其中 overlay 网络类型用于 Swarm mode

pid

跟主机系统共享进程命名空间。打开该选项的容器之间,以及容器和宿主机系统之间可以通过进程 ID 来相互访问和操作。

pid: "host"

ports

暴露端口信息。

使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

ports:
 - "3000"
 - "8000:8000"
 - "49100:22"
 - "127.0.0.1:8001:8001"

注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。

secrets

存储敏感数据,例如 mysql 服务密码。

version: "3"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
  secrets:
    - db_root_password
    - my_other_secret

secrets:
  my_secret:
    file: ./my_secret.txt
  my_other_secret:
    external: true

security_opt

指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)。例如配置标签的用户名和角色名。

security_opt:
    - label:user:USER
    - label:role:ROLE

stop_signal

设置另一个信号来停止容器。在默认情况下使用的是 SIGTERM 停止容器。

stop_signal: SIGUSR1

sysctls

配置容器内核参数。

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

ulimits

指定容器的 ulimits 限制值。

例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes

数据卷所挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。

该指令中路径支持相对路径。

volumes:
 - /var/lib/mysql
 - cache/:/tmp/cache
 - ~/configs:/etc/configs/:ro

其它指令

此外,还有包括 domainname, entrypoint, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir 等指令,基本跟 docker run 中对应参数的功能一致。

指定服务容器启动后执行的入口文件。

entrypoint: /code/entrypoint.sh

指定容器中运行应用的用户名。

user: nginx

指定容器中工作目录。

working_dir: /code

指定容器中搜索域名、主机名、mac 地址等。

domainname: your_website.com
hostname: test
mac_address: 08-00-27-00-0C-0A

允许容器中运行一些特权命令。

privileged: true

指定容器退出后的重启策略为始终重启。该命令对保持服务始终运行十分有效,在生产环境中推荐配置为 always 或者 unless-stopped

restart: always

以只读模式挂载容器的 root 文件系统,意味着不能对容器内容进行修改。

read_only: true

打开标准输入,可以接受外部输入。

stdin_open: true

模拟一个伪终端。

tty: true

 

 

 

 

读取变量

Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 .env 文件中的变量。

例如,下面的 Compose 文件将从运行它的环境中读取变量 ${MONGO_VERSION} 的值,并写入执行的指令中。

version: "3"
services:

db:
  image: "mongo:${MONGO_VERSION}"

如果执行 MONGO_VERSION=3.2 docker-compose up 则会启动一个 mongo:3.2 镜像的容器;如果执行 MONGO_VERSION=2.8 docker-compose up 则会启动一个 mongo:2.8 镜像的容器。

若当前目录存在 .env 文件,执行 docker-compose 命令时将从该文件中读取变量。

在当前目录新建 .env 文件并写入以下内容。

# 支持 # 号注释
MONGO_VERSION=3.6

执行 docker-compose up 则会启动一个 mongo:3.6 镜像的容器。

官方例子

version: "3"
services:

  redis:
    image: redis:alpine
    ports:
      - "6379"
    networks:
      - frontend
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  db:
    image: postgres:9.4
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - backend
    deploy:
      placement:
        constraints: [node.role == manager]
  vote:
    image: dockersamples/examplevotingapp_vote:before
    ports:
      - 5000:80
    networks:
      - frontend
    depends_on:
      - redis
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
      restart_policy:
        condition: on-failure
  result:
    image: dockersamples/examplevotingapp_result:before
    ports:
      - 5001:80
    networks:
      - backend
    depends_on:
      - db
    deploy:
      replicas: 1
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure

  worker:
    image: dockersamples/examplevotingapp_worker
    networks:
      - frontend
      - backend
    deploy:
      mode: replicated
      replicas: 1
      labels: [APP=VOTING]
      restart_policy:
        condition: on-failure
        delay: 10s
        max_attempts: 3
        window: 120s
      placement:
        constraints: [node.role == manager]

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]

networks:
  frontend:
  backend:

volumes:
  db-data:

作者:左蓝
链接:https://www.jianshu.com/p/748416621013
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

理解多compose文件组合

默认,compose会读取两个文件,一个docker-compose.yml和一个可选的docker-compose.override.yml文件。通常,docker-compose.yml文件包含你的基本配置,而docker-compose.override.yml,顾名思义,就是包含的现有服务配置的覆盖内容,或完全新的配置。

如果一个服务在这两个文件中都有定义,那么compose将使用添加和覆盖配置中所描述的规则来合并服务

要使用多个override文件或不同名称的override文件,可以使用-f选项来指定文件列表。compose根据在命令行指定的顺序来合并它们

当使用多个配置文件时,必须确保文件中所有的路径都是相对于base compose文件的(-f 指定的第一个compose文件)。这样要求是因为override文件不需要一个有效的compose文件。override文件可以只包含配置中的一小片段。跟踪一个服务的片段是相对于那个路径的,这是很困难的事,所以一定要保持路径容易理解,所以路径必须定义为相对于base文件的路径。

例如,定义两个配置文件:

docker-compose.yml

web:
  image: example/my_web_app:latest
  links:
    - db
    - cache

db:
  image: postgres:latest

cache:
  image: redis:latest

docker-compose.prod.yml

web:
  ports:
    - 80:80
  environment:
    PRODUCTION: 'true'

cache:
  environment:
    TTL: '500'

要使用这个生产compose文件部署,运行如下命令:

docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

这将会使用docker-compose.ymldocker-compose.prod.yml来部署这三个服务

Docker Machine

Docker Machine 是供给和管理 docker 化主机的工具。有自己的命令行客户端 docker-machine。提供多种环境的 docker 主机,可以用 Docker Machine 在一个或者多个虚拟系统(本地或者远程)上安装 Docker Engine。

Install

curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine

uninstall

sudo rm $(which docker-machine)

Zsh命令补全

mkdir -p ~/.zsh/completion
curl -L https://raw.githubusercontent.com/docker/machine/master/contrib/completion/zsh/_docker-machine > ~/.zsh/completion/_docker-machine

~/.zshrc添加:

注意:(如果是oh-my-zsh,在$ZSH/oh-my-zsh.sh中添加)

fpath=(~/.zsh/completion $fpath)

执行:

autoload -Uz compinit && compinit -i
exec $SHELL -l

Usage

确保已经安装了virtualbox

sudo apt install virtualbox

创建本地实例:

使用 virtualbox 类型的驱动,创建一台 Docker 主机,命名为 test。

docker-machine create -d virtualbox test

你也可以在创建时加上如下参数,来配置主机或者主机上的 Docker。

--engine-opt dns=114.114.114.114 配置 Docker 的默认 DNS

--engine-registry-mirror https://registry.docker-cn.com 配置 Docker 的仓库镜像

--engine-insecure-registry

--virtualbox-memory 2048 配置主机内存

--virtualbox-cpu-count 2 配置主机 CPU

 

更多参数请使用 docker-machine create --driver virtualbox --help 命令查看。

$ docker-machine create --driver virtualbox --help
Usage: docker-machine create [OPTIONS] [arg...]

Create a machine.

Run 'docker-machine create --driver name' to include the create flags for that driver in the help text.

Options:

--driver, -d "none" Driver to create machine with.
--engine-env [--engine-env option --engine-env option] Specify environment variables to set in the engine
--engine-insecure-registry [--engine-insecure-registry option --engine-insecure-registry option] Specify insecure registries to allow with the created engine
--engine-install-url "https://get.docker.com" Custom URL to use for engine installation [$MACHINE_DOCKER_INSTALL_URL]
--engine-label [--engine-label option --engine-label option] Specify labels for the created engine
--engine-opt [--engine-opt option --engine-opt option] Specify arbitrary flags to include with the created engine in the form flag=value
--engine-registry-mirror [--engine-registry-mirror option --engine-registry-mirror option] Specify registry mirrors to use [$ENGINE_REGISTRY_MIRROR]
--engine-storage-driver Specify a storage driver to use with the engine
--swarm Configure Machine with Swarm
--swarm-addr addr to advertise for Swarm (default: detect and use the machine IP)
--swarm-discovery Discovery service to use with Swarm
--swarm-experimental Enable Swarm experimental features
--swarm-host "tcp://0.0.0.0:3376" ip/socket to listen on for Swarm master
--swarm-image "swarm:latest" Specify Docker image to use for Swarm [$MACHINE_SWARM_IMAGE]
--swarm-master Configure Machine to be a Swarm master
--swarm-opt [--swarm-opt option --swarm-opt option] Define arbitrary flags for swarm
--swarm-strategy "spread" Define a default scheduling strategy for Swarm
--virtualbox-boot2docker-url The URL of the boot2docker image. Defaults to the latest available version [$VIRTUALBOX_BOOT2DOCKER_URL]
--virtualbox-cpu-count "1" number of CPUs for the machine (-1 to use the number of CPUs available) [$VIRTUALBOX_CPU_COUNT]
--virtualbox-disk-size "20000" Size of disk for host in MB [$VIRTUALBOX_DISK_SIZE]
--virtualbox-host-dns-resolver Use the host DNS resolver [$VIRTUALBOX_HOST_DNS_RESOLVER]
--virtualbox-dns-proxy Proxy all DNS requests to the host [$VIRTUALBOX_DNS_PROXY]
--virtualbox-hostonly-cidr "192.168.99.1/24" Specify the Host Only CIDR [$VIRTUALBOX_HOSTONLY_CIDR]
--virtualbox-hostonly-nicpromisc "deny" Specify the Host Only Network Adapter Promiscuous Mode [$VIRTUALBOX_HOSTONLY_NIC_PROMISC]
--virtualbox-hostonly-nictype "82540EM" Specify the Host Only Network Adapter Type [$VIRTUALBOX_HOSTONLY_NIC_TYPE]
--virtualbox-import-boot2docker-vm The name of a Boot2Docker VM to import
--virtualbox-memory "1024" Size of memory for host in MB [$VIRTUALBOX_MEMORY_SIZE]
--virtualbox-no-share Disable the mount of your home directory
创建好主机之后,查看主机

docker-machine ls

NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
test - virtualbox Running tcp://192.168.99.187:2376 v17.10.0-ce

 

 

创建主机成功后,可以通过 env 命令来让后续操作对象都是目标主机。

docker-machine env test

后续根据提示在命令行输入命令之后就可以操作 test 主机。

通过以下命令恢复当前环境:

docker-machine env -u

也可以通过 SSH 登录到主机。

docker-machine ssh test

连接到主机之后你就可以在其上使用 Docker 了。

操作命令

  • active 查看活跃的 Docker 主机
  • config 输出连接的配置信息
  • create 创建一个 Docker 主机
  • env 显示连接到某个主机需要的环境变量
  • inspect 输出主机更多信息
  • ip 获取主机地址
  • kill 停止某个主机
  • ls 列出所有管理的主机
  • provision 重新设置一个已存在的主机
  • regenerate-certs 为某个主机重新生成 TLS 认证信息
  • restart 重启主机
  • rm 删除某台主机
  • ssh SSH 到主机上执行命令
  • scp 在主机之间复制文件
  • mount 挂载主机目录到本地
  • start 启动一个主机
  • status 查看主机状态
  • stop 停止一个主机
  • upgrade 更新主机 Docker 版本为最新
  • url 获取主机的 URL
  • version 输出 docker-machine 版本信息
  • help 输出帮助信息

每个命令,又带有不同的参数,可以通过

$ docker-machine COMMAND --help

来查看具体的用法。

注意:docker-machine 安装的 Docker 在 /etc/systemd/system 目录下多出了一个 Docker 相关的目录:docker.service.d。这个目录中只有一个文件 10-machine.conf,这个配置文件至关重要,因为它会覆盖 Docker 默认安装时的配置文件,从而以 Docker Machine 指定的方式启动 Docker daemon。至此我们有了一个可以被远程访问的 Docker daemon。

加入其他物理主机

https://docs.docker.com/machine/drivers/generic/

在使用 docker-machine 进行远程安装前我们需要做一些准备工作:
1. 在目标主机上创建一个用户并加入sudo 组
2. 为该用户设置 sudo 操作不需要输入密码
3. 把本地用户的 ssh public key 添加到目标主机上

注意:如果远程物理级已经安装过docker,docker-machine会把远程的docker重置,镜像以及容器都没了…

比如我们要在远程主机上添加一个名为 nick 的用户并加入 sudo 组:

$ sudo adduser nick
$ sudo usermod -a -G sudo nick

然后设置 sudo 操作不需要输入密码:

$ sudo visudo

把下面一行内容添加到%sudo ALL=(ALL:ALL) ALL之后并保存文件,否则不生效:

%sudo  ALL=(ALL:ALL) ALL
nick   ALL=(ALL:ALL) NOPASSWD: ALL

最后把本地用户的 ssh public key 添加到目标主机上:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub nick@xxx.xxx.xxx.xxx

这几步操作的主要目的是获得足够的权限可以远程的操作目标主机。

然后添加machine:

docker-machine create \               
  --driver generic \
  --generic-ip-address=192.168.6.105 \
  --generic-ssh-key ~/.ssh/id_rsa \
  --generic-ssh-user=dworker \
  --engine-registry-mirror https://vioqnt7w.mirror.aliyuncs.com \
  --engine-insecure-registry 192.168.6.113:8888 \
  qww-machine
  [machine name]

如果已安装docker:

docker-machine create -d none --url=tcp://192.168.6.105:2375 vmware_docker01

添加镜像加速

$ docker-machine ssh default
$> sudo sed -i "s|EXTRA_ARGS='|EXTRA_ARGS='--registry-mirror=$REGISTRY_MIRROR |g" /var/lib/boot2docker/profile
$> exit
$ docker-machine restart default

Swarm Mode

Docker 1.12 Swarm mode 已经内嵌入 Docker 引擎,成为了 docker 子命令 docker swarm。请注意与旧的 Docker Swarm 区分开来。

Swarm mode 内置 kv 存储功能,提供了众多的新特性,比如:具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。使得 Docker 原生的 Swarm 集群具备与 Mesos、Kubernetes 竞争的实力。

功能特点

与Docker Engine集成的集群管理

使用Docker Engine CLI创建一组Docker引擎,您可以在其中部署应用程序服务。您不需要其他编排软件来创建或管理群集。

节点分散式设计

Docker Engine不是在部署时处理节点角色之间的差异,而是在运行时处理角色变化。您可以使用Docker Engine部署两种类型的节点,管理节点和工作节点。这意味着您可以从单个服务器构建整个群集。

声明性服务模型

Docker Engine使用声明性方法来定义应用程序堆栈中各种服务的所需状态。例如,您可以描述由具有消息队列服务和数据库后端的Web前端服务组成的应用程序。

可扩容与缩放容器

对于每个服务,您可以声明要运行的任务数。当您向上或向下缩放时,swarm管理器通过添加或删除任务来自动适应,以保持所需的任务数量来保证集群的可靠状态。

容器容错状态协调

群集管理器节点不断监视群集状态,并协调您表示的期望状态的实际状态之间的任何差异。例如,如果设置一个服务以运行容器的10个副本,并且托管其中两个副本的工作程序计算机崩溃,则管理器将创建两个新副本以替换崩溃的副本。 swarm管理器将新副本分配给正在运行和可用的worker节点上。

多主机网络

您可以为服务指定覆盖网络。当swarm管理器初始化或更新应用程序时,它会自动为覆盖网络上的容器分配地址。

服务发现

Swarm管理器节点为swarm中的每个服务分配唯一的DNS名称,并负载平衡运行的容器。您可以通过嵌入在swarm中的DNS服务器查询在群中运行的每个容器。

负载平衡

您可以将服务的端口公开给外部负载平衡器。在内部,swarm允许您指定如何在节点之间分发服务容器。

缺省安全

群中的每个节点强制执行TLS相互验证和加密,以保护其自身与所有其他节点之间的通信。您可以选择使用自签名根证书或来自自定义根CA的证书。

滚动更新

在已经运行期间,您可以增量地应用服务更新到节点。 swarm管理器允许您控制将服务部署到不同节点集之间的延迟。如果出现任何问题,您可以将任务回滚到服务的先前版本。

概念

节点

运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。

节点分为管理 (manager) 节点和工作 (worker) 节点。

管理节点用于 Swarm 集群的管理,docker swarm 命令基本只能在管理节点执行(节点退出集群命令 docker swarm leave 可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为 leaderleader 通过 raft 协议实现。

工作节点是任务执行节点,管理节点将服务 (service) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。

服务和任务

任务 (Task)是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器。

服务 (Services) 是指一组任务的集合,服务定义了任务的属性。服务有两种模式:

  • replicated services 按照一定规则在各个工作节点上运行指定个数的任务。
  • global services 每个工作节点上运行一个任务

两种模式通过 docker service create--mode 参数指定。

下图解释服务、任务、容器:

服务的任务及调试说明:

服务部署的复制模式和全局模式说明:

开启API端口监听

(下面的Portainer需要用到)

Swarm是通过监听2375端口进行通信的,所以在使用Swarm进行集群管理之前,需要设置一下2375端口的监听。这里有两种方法,一种是通过修改docker配置文件方式,另一种是通过一个轻量级的代理容器进行监听。

方式一,修改配置文件(推荐):

/etc/default/docker中的DOCKER_OPTS追加配置:

-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

或者在/etc/docker/daemon.json添加(需要高版本Docker):

{
  "hosts": [
    "tcp://0.0.0.0:2375",
    "unix:///var/run/docker.sock"
  ]
}

方式二,添加代理

docker run -ti -d -p 2375:2375 \
--restart=always \
--hostname=$HOSTNAME \
--name shipyard-proxy \
-v /var/run/docker.sock:/var/run/docker.sock \
-e PORT=2375 \
shipyard/docker-proxy

创建集群

 
在创建集群前,如果开启了防火墙,请确认三台主机的防火墙能让swarm需求的端口开放,需要打开主机之间的端口,以下端口必须可用。在某些系统上,这些端口默认为打开。
2377:TCP端口2377用于集群管理通信
7946:TCP和UDP端口7946用于节点之间的通信
4789:TCP和UDP端口4789用于覆盖网络流量
如果您计划使用加密(–opt加密)创建覆盖网络,则还需要确保协议50(ESP)已打开。

docker swarm命令:

docker swarm init --advertise-addr 172.18.60.133

#恢复
docker swarm init --advertise-addr 172.18.60.133 --force-new-cluster

#其它节点加入
docker swarm join --token \
SWMTKN-1-44gjumnutrh4k9lls54f5hp43kiioxf16iuh7qarjfqjsu7jio-2326b8ikb1xiysm3i7neh9nho 172.18.60.133:2377

#输出可以用来以worker角色加入的token
docker swarm join-token worker

#输出可以用来以manager角色加入的token
docker swarm join-token manager

#manager节点强制脱离
docker swarm leave --force

#worker节点脱离
docker swarm leave

#节点从swarm中移除
docker node rm XXXXX

#worker节点提升为manager
docker node promote ilog2

#恢复为worker
docker node demote <NODE>

#创建服务
docker service create --replicas 3 --name helloworld alpine ping docker.com

 

节点管理

查看集群中的docker信息

docker -H 10.0.11.150:2376 info

列出节点

docker node ls

说明:
AVAILABILITY列
显示调度程序是否可以将任务分配给节点:

  • Active 意味着调度程序可以将任务分配给节点。
  • Pause 意味着调度程序不会将新任务分配给节点,但现有任务仍在运行。
  • Drain 意味着调度程序不会向节点分配新任务。调度程序关闭所有现有任务并在可用节点上调度它们。

MANAGER STATUS列
显示节点是属于manager或者worker

  • 没有值 表示不参与群管理的工作节点。
  • Leader 意味着该节点是使得群的所有群管理和编排决策的主要管理器节点。
  • Reachable 意味着节点是管理者节点正在参与Raft共识。如果领导节点不可用,则该节点有资格被选为新领导者。
  • Unavailable 意味着节点是不能与其他管理器通信的管理器。如果管理器节点不可用,您应该将新的管理器节点加入群集,或者将工作器节点升级为管理器。

查看节点的详细信息

您可以在管理器节点上运行docker node inspect来查看单个节点的详细信息。 输出默认为JSON格式,但您可以传递–pretty标志以以可读的yml格式打印结果

# ybd @ ybd-PC in ~ [9:37:23]
$ docker node inspect --pretty ybd-machine1
ID: f917bibevklfp3xjsjoyx2g2t
Hostname: ybd-machine1
Joined at: 2018-01-03 10:00:28.499769713 +0000 utc
Status:
State: Ready
Availability: Active
Address: 192.168.6.113
Platform:
Operating System: linux
Architecture: x86_64
Resources:
CPUs: 1
Memory: 995.9MiB
Plugins:
Log: awslogs, fluentd, gcplogs, gelf, journald, json-file, logentries, splunk, syslog
Network: bridge, host, macvlan, null, overlay
Volume: local
Engine Version: 17.12.0-ce
Engine Labels:
- provider=virtualbox
TLS Info:
TrustRoot:
-----BEGIN CERTIFICATE-----
MIIBajCCARCgAwIBAgIUTdhfszkLcL0IC92X4TaOWbQlbZAwCgYIKoZIzj0EAwIw
EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcxMjIyMDg0NzAwWhcNMzcxMjE3MDg0
NzAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH
A0IABEWabJlpAGjNi6x8QWGXnMUFwPe27anM5nHwLX8y05TbgamYvV7Is4CZ1BbU
ypJ/a9FpSp4FbV/6iYveIwwaHLSjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
Af8EBTADAQH/MB0GA1UdDgQWBBR1K7f/HuhGDD2gzDeejaH2r8ZxIzAKBggqhkjO
PQQDAgNIADBFAiEApL0o/FwwzLrhalYddR+buFHg0Hg3jKh37t00TmMU7SICIAOz
YZNcngOkQiY2K2poQqRw+dFU9xOk543G+zDHqX4h
-----END CERTIFICATE-----

Issuer Subject: MBMxETAPBgNVBAMTCHN3YXJtLWNh
Issuer Public Key: MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERZpsmWkAaM2LrHxBYZecxQXA97btqczmcfAtfzLTlNuBqZi9XsizgJnUFtTKkn9r0WlKngVtX/qJi94jDBoctA==

 

更新节点

Usage: docker node update [OPTIONS] NODE

Options:
–availability string Availability of the node (“active”|”pause”|”drain”)
–label-add list Add or update a node label (key=value)
–label-rm list Remove a node label if exists
–role string Role of the node (“worker”|”manager”)

升级或降级节点

您可以将工作程序节点提升为manager角色。这在管理器节点不可用或者您希望使管理器脱机以进行维护时很有用。 类似地,您可以将管理器节点降级为worker角色。
无论您升级或降级节点,您应该始终在群中维护奇数个管理器节点。
要升级一个节点或一组节点,请从管理器节点运行:

docker node promote [NODE]
docker node domote [NODE]

退出docker swarm集群

work节点:

docker swarm leave

manager节点:

docker swarm leave -f

可视化visualizer服务

docker service create \
--name=viz \
--publish=8088:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer

Service用法

创建服务
docker service create \
--image nginx \
--replicas 2 \
nginx
 
更新服务
docker service update \
--image nginx:alpine \
nginx
 
删除服务
docker service rm nginx
 
减少服务实例(这比直接删除服务要好)
docker service scale nginx=0
 
增加服务实例
docker service scale nginx=5
 
查看所有服务
docker service ls
 
查看服务的容器状态
docker service ps nginx
 
查看服务的详细信息。
docker service inspect nginx

实现零宕机部署也非常简单。这样也可以方便地实现持续部署:

构建新镜像
docker build -t hub.docker.com/image .
 
将新镜像上传到Docker仓库
docker push hub.docker.com/image
 
更新服务的镜像
docker service update --image hub.docker.com/image service

更新服务要慎重。 你的容器同时运行在多个主机上。更新服务时,只需要更新Docker镜像。合理的测试和部署流程是保证成功的关键。Swarm非常容易入门。分布式系统通常是非常复杂的。与其他容器集群系统(Mesos, Kubernetes)相比,Swarm的学习曲线最低

Docker Visual Management

Rancher

官方网站

如果是对集群管理并且管理员只限制Docker命令权限的话,建议用这个工具,商店用起来都比较方便,

优点:界面中文化,操作简单易懂,功能强大,容灾机制。

缺点: 不能团队分配权限,容器操作权限太大没法满足需求,部署时相应的Docker 服务也很多,需要逐一去了解容器作用。

Shipyard

官方网站

Shipyard是在Docker Swarm的基础上,管理Docker资源,包括容器,镜像,注册表等。

优点

  1. 支持镜像管理、容器管理。
  2. 支持控制台命令
  3. 容器资源消耗监控
  4. 支持集群swarm,可以随意增加节点
  5. 支持控制用户管理权限,可以设置某个容器对某个用户只读、管理权限。
  6. 有汉化版

缺点

  1. 启动容器较多,占用每个节点的一部分资源

部署:

curl -sSL https://shipyard-project.com/deploy | bash -s

注意:这将在端口2375上暴露Docker Engine。如果此节点可以在安全网络之外访问,建议使用TLS。

支持集群,所以可以添加节点:

curl -sSL https://shipyard-project.com/deploy | ACTION=node DISCOVERY=etcd://10.0.0.10:4001 bash -s

它会下载并启动7个镜像:

界面:

容器信息:

初体验来说,感觉跟下面的Portainer功能差不多,但是Registry总是添加失败

Portainer

官方网站

PortainerDocker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。

优点

  1. 支持容器管理、镜像管理
  2. 轻量级,消耗资源少
  3. 基于docker api,安全性高,可指定docker api端口,支持TLS证书认证。
  4. 支持权限分配
  5. 支持集群

缺点

  1. 功能不够强大。
  2. 容器创建后,无法通过后台增加端口。
  3. 没有容灾机制

单机启动:

docker run -d -p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer

swarm模式启动:

docker service create \
--name portainer \
--publish 9000:9000 \
--constraint 'node.role == manager' \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=bind,src=/path/on/host/data,dst=/data \
portainer/portainer \
-H unix:///var/run/docker.sock

容器管理:

镜像管理:

镜像仓库:

Endpoints:

注意:添加Endpoints先要暴露节点的2375端口。

Finally

参考:

Docker — 从入门到实践

在生产环境中使用Docker Swarm的一些建议

使用Docker Harbor搭建私有镜像服务器和Mirror服务器

远程连接docker daemon,Docker Remote API

 

来源: http://yangbingdong.com/2018/docker-visual-management-and-orchestrate-tools/

Docker实践记录(二):使用Harbor搭建Docker私有仓库

写在前面:

针对于公司内部使用的镜像,我们希望推送到本地的私有docker仓库中,以供公司内部相关人员下载使用,所以准备研究使用harbor完成此功能,此文章只是研究,实际生产环境需要采用高可用的架构,之后也会搭建研究。

Harbor介绍:

Harbor是VMware公司开源的企业级DockerRegistry项目,项目地址为https://github.com/vmware/harbor。其目标是帮助用户迅速搭建一个企业级的Dockerregistry服务。它以Docker公司开源的registry为基础,提供了管理UI,基于角色的访问控制(Role Based Access Control),AD/LDAP集成、以及审计日志(Auditlogging) 等企业用户需求的功能,同时还原生支持中文。Harbor的每个组件都是以docker容器的形式构建的,使用Docker Compose来对它进行部署。

Harbor的特点:

  • 基于角色的访问控制 - 用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。
  • 镜像复制 - 镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。
  • 图形化用户界面 - 用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。
  • AD/LDAP 支持 - Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理。
  • 审计管理 - 所有针对镜像仓库的操作都可以被记录追溯,用于审计管理。
  • 国际化 - 已拥有英文、中文、德文、日文和俄文的本地化版本。更多的语言将会添加进来。
  • RESTful API - RESTful API 提供给管理员对于Harbor更多的操控, 使得与其它管理软件集成变得更容易。
  • 部署简单 - 提供在线和离线两种安装工具,也可以安装到vSphere平台(OVA方式)虚拟设备。

Harbor基于Docker Registry做了增强,添加了很多企业级管理需要的能力,使原来能力较弱的Docker Registry更适合于生产环境中使用。

Harbor整体架构:

20170810165828

Harbor在架构上主要由五个组件构成:

  • Proxy:Harbor的registry, UI, token等服务,通过一个前置的反向代理统一接收浏览器、Docker客户端的请求,并将请求转发给后端不同的服务。
  • Registry: 负责储存Docker镜像,并处理dockerpush/pull 命令。由于我们要对用户进行访问控制,即不同用户对Docker image有不同的读写权限,Registry会指向一个token服务,强制用户的每次docker pull/push请求都要携带一个合法的token,Registry会通过公钥对token 进行解密验证。
  • Core services: 这是Harbor的核心功能,主要提供以下服务:UI:提供图形化界面,帮助用户管理registry上的镜像(image), 并对用户进行授权。 webhook:为了及时获取registry上image状态变化的情况, 在Registry上配置webhook,把状态变化传递给UI模块。token服务:负责根据用户权限给每个docker push/pull命令签发token.Docker客户端向Regiøstry服务发起的请求,如果不包含token,会被重定向到这里,获得token后再重新向Registry进行请求。
  • Database:为coreservices提供数据库服务,负责储存用户权限、审计日志、Docker image分组信息等数据。
  • Log collector:为了帮助监控Harbor运行,负责收集其他组件的log,供日后进行分析。

这几个Contianer 通过 Docker link 的形式连接在一起,在容器之间通过容器名字互相访问。对终端用户而言,只需要暴露 proxy(即Nginx)的服务端口即可。

Harbor认证流程:

20170810161227

  • 首先,请求被代理容器监听拦截,并跳转到指定的认证服务器。
  • 如果认证服务器配置了权限认证,则会返回401。通知dockerclient在特定的请求中需要带上一个合法的token。而认证的逻辑地址则指向架构图中的core services。
  • 当docker client接受到错误code。client就会发送认证请求(带有用户名和密码)到coreservices进行basic auth认证。
  • 当上面的请求发送给ngnix以后,ngnix会根据配置的认证地址将带有用户名和密码的请求发送到core serivces。
  • coreservices获取用户名和密码以后对用户信息进行认证(自己的数据库或者介入LDAP都可以)。成功以后,返回认证成功的信息。
  • 从上面的docker registry 和 Harbor的架构图、流程图可以看出Harbor的扩展部分为coreservices。这部分实现了用户的认证,添加了UI模块已经webhook。

Harbor的核心概念:

20170810165951

以上是Harbor的核心概念。一个项目可以看成一个用户的小私库,项目成员按照其角色,可以上传,下载,删除镜像,或添加删除成员等。系统管理员可以创建镜像库复制目标,为项目设置复制策略,可以从其它的镜像库复制镜像过来。复制策略会产生复制任务。项目下面可拥有多个镜像,而每个镜像则可以有多个镜像标签。项目包含日志。

Harbor的安全机制

企业中的软件研发团队往往划分为诸多角色,如项目经理、产品经理、测试、运维等。在实际的软件开发和运维过程中,这些角色对于镜像的使用需求是不一样的。从安全的角度,也是需要通过某种机制来进行权限控制的。

举例来说,开发人员显然需要拥有对镜像的读写(PULL/PUSH)权限以更新和改正代码;测试人员中需要读取(PULL)权限;而项目经理需要对上述的角色进行管理。

Harbor为这种需求提供了用户和成员两种管理概念。

在Harbor中,用户主要分为两类。一类为管理员,另一类为普通用户。两类用户都可以成为项目的成员。而管理员可以对用户进行管理。

成员是对应于项目的概念,分为三类:管理员、开发者、访客。

管理员可以对开发者和访客作权限的配置和管理。

测试和运维人员可以访客身份读取项目镜像,或者公共镜像库中的文件。
从项目的角度出发,显然项目管理员拥有最大的项目权限,如果要对用户进行禁用或限权等,可以通过修改用户在项目中的成员角色来实现,甚至将用户移除出这个项目。

20170810184342

Harbor的镜像同步

为什么需要镜像同步

由于对镜像的访问是一个核心的容器概念,在实际使用过程中,一个镜像库可能是不够用的,下例情况下,我们可能会需要部署多个镜像仓库:

  • 国外的公有镜像下载过慢,需要一个中转仓库进行加速
  • 容器规模较大,一个镜像仓库不堪重负
  • 对系统稳定性要求高,需要多个仓库保证高可用性
  • 镜像仓库有多级规划,下级仓库依赖上级仓库

更常用的场景是,在企业级软件环境中,会在软件开发的不同阶段存在不同的镜像仓库,

  • 在开发环境库,开发人员频繁修改镜像,一旦代码完成,生成稳定的镜像即需要同步到测试环境。
  • 在测试环境库,测试人员对镜像是只读操作,测试完成后,将镜像同步到预上线环境库。
  • 在预上线环境库,运维人员对镜像也是只读操作,一旦运行正常,即将镜像同步到生产环境库。
  • 在这个流程中,各环境的镜像库之间都需要镜像的同步和复制。
Harbor的镜像同步机制

有了多个镜像仓库,在多个仓库之间进行镜像同步马上就成为了一个普遍的需求。比较传统的镜像同步方式,有两种:

第一种方案,使用Linux提供的RSYNC服务来定义两个仓库之间的镜像数据同步。

第二种方案,对于使用IaaS服务进行镜像存储的场景,利用IaaS的配置工具来对镜像的同步进行配置。

这两种方案都依赖于仓库所在的存储环境,而需要采用不同的工具策略。Harbor则提供了更加灵活的方案来处理镜像的同步,其核心是三个概念:

用Harbor自己的API来进行镜像下载和传输,作到与底层存储环境解耦。

利用任务调度和监控机制进行复制任务的管理,保障复制任务的健壮性。在同步过程中,如果源镜像已删除,

Harbor会自动同步删除远端的镜像。在镜像同步复制的过程中,Harbor会监控整个复制过程,遇到网络等错误,会自动重试。

提供复制策略机制保证项目级的复制需求。在Harbor中,可以在项目中创建复制策略,来实现对镜像的同步。与Docker Registry的不同之处在于,Harbor的复制是推(PUSH)的策略,由源端发起,而Docker Registry的复制是拉(PULL)的策略,由目标端发起。

20170810184523

Harbor的多级部署

在实际的企业级生产运维场景,往往需要跨地域,跨层级进行镜像的同步复制,比如集团企业从总部到省公司,由省公司再市公司的场景。

这一部署场景可简化如下图:

20170810184607

更复杂的部署场景如下图:

20170810184623

PS:以上内容转载自网络

环境准备:

系统版本:Centos7.3
docker版本:1.17.06
harbor版本:1.1.2
docker-cmopose版本:1.14.0
python版本:2.7.5
harbor server IP地址:192.168.162.54

一、安装docker

安装方法请参考之前文章:http://www.jiagoumi.com/work/1204.html

二、安装docker-compose

# curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# docker-compose --version
docker-compose version 1.14.0, build c7bdf9e
注意:
如果执行docker-compose --version命令后报如下错误:
Cannot open self /usr/local/bin/docker-compose or archive /usr/local/bin/docker-compose.pkg
解决办法:
可能是使用curl下载下来的文件是不完整导致,可以登录https://github.com/docker/compose/releases之间选择版本下载,例如我要安装docker-cmopose版本的版本为1.14.0,则我需要下载docker-compose-Linux-x86_64,替换原来的,如下:
# mv /usr/local/bin/docker-compose /usr/local/bin/docker-compose.bak
# mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
# du -sh  /usr/local/bin/docker-compose*
8.5M /usr/local/bin/docker-compose       ---->新
2.2M /usr/local/bin/docker-compose.bak    ---->旧
可以看到新的文件比原来的大很多,接着执行命令就正常了
# docker-compose --version
docker-compose version 1.14.0, build c7bdf9e

三、搭建Harbor服务

官方系统需求: On a Linux host: docker 1.10.0+ and docker-compose 1.6.0+ .
1、下载源代码:
网上很多文章采用git方式下载,但是如果你按照这种方式下载的话,解压后你再按照网上的文章安装的话,最终你是没办法正常访问harbor的页面的,坑很大!推荐下载源码的方式安装,如下图所示:
20170810131750
源码包下载地址:https://github.com/vmware/harbor/releases
选择下图中的包下载上传到服务器后解压。
20170811103512
# tar zxf harbor-offline-installer-v1.1.2.tgz
# mv harbor /opt/
2、修改harbor.cfg配置
harbor.cfg常用配置参数解释:
hostname: 配置目标主机的主机名, 被用来访问Harbor ui 和镜像仓库的,可以配置为ip地址和全域名,比如 192.168.1.10 or reg.yourdomain.com. 不要使用 localhost or 127.0.0.1 为主机名
ui_url_protocol: (http or https. 默认协议为 http) 该协议被用来访问 the UI and the token/notification 服务. 默认是 http. 想要设置https协议,请看链接 配置Harbor支持https协议.
Email settings: 配置Harbor来发送邮件,当然改配置并不是必须的 .注意:默认的ssl链接没有被启用,如果SMTP需要ssl支持,可以设置以下参数以支持。
email_ssl = true
  * email_server = smtp.mydomain.com
  * email_server_port = 25
  * email_username = sample_admin@mydomain.com
  * email_password = abc
  * email_from = admin <sample_admin@mydomain.com> 
  * email_ssl = false       
harbor_admin_password: 设置管理员内部密码,该密码紧紧在第一次启动Harbor的时候生效.在之后这个设置被忽略,管理员的密码将在UI中重新设置。 默认的用户名和密码如下: admin/Harbor12345 .
auth_mode: 被用来认证的方式,默认使用的是 db_auth,该认证会被肢解存储到数据库中。 如果需要设置LDAP方式认证需要使用ldap_auth.
ldap_url: LDAP认证方式的URL (e.g. ldaps://ldap.mydomain.com). 当 auth_mode 被设置为ldap_auth 的时候。
ldap_searchdn: 链接LDAP/AD服务的用户域(e.g. uid=admin,ou=people,dc=mydomain,dc=com).
ldap_search_pwd: 为上面设定的用户域设置密码 ldap_searchdn.
ldap_basedn: 基础域为方便寻找一个用户e.g. ou=people,dc=mydomain,dc=com. 仅当 auth_mode is 设置为ldap_auth的时候才使用
ldap_filter:用户搜索过滤 (objectClass=person).
ldap_uid: 该参数被用来匹配一个LDAP搜索的用户,可以使uid,cn,email或者其他的方式。 
ldap_scope: 用户搜索范围, 1-LDAP_SCOPE_BASE, 2-LDAP_SCOPE_ONELEVEL, 3-LDAP_SCOPE_SUBTREE. Default is 3.
db_password: mysql数据库root用户密码 db_auth.
self_registration: (on or off. Default is on) 启用和关闭用户注册功能.当被关闭,新用户职能通过admin用户去创建。 _注意: 当 auth_mode 被设置为 ldap_auth, self-registration 会被一直关闭,该参数也会被忽略。
use_compressed_js: (on or off. 默认为 on) 生产中使用,建议将该参数设置为 on. 在部署模式中将参数设置为off 以至于js 文件能够被分开去修改.
max_job_workers: (默认为 3) 设置在任务服务中最大的工作副本, 每一个image副本任务,会有一个worker从仓库中将所有的tag同步到远端。增大这个值回允许更多当前的副本任务,然而因为每个worker都会去消耗一定的网络/cpu/io等资源,必须根据系统的资源进行合理设置该值。
secretkey_path: 默认是/data,其下的secretkey文件存储值为加解密在副本策略中远端仓库的密码,长度为16位字符。生产中必需修改该值. NOTE: After changing this key, previously encrypted password of a policy can not be decrypted.
token_expiration: token过期时间,默认30分钟
verify_remote_cert: (on or off. 默认 on) 该参数决定了当harbor盒远端的registry实例交互的时候是否使用SSL/TLS .设置为off 的时候,一般远端的registry会采用自签名或者未受信任的证书。
customize_crt: (on or off. 默认为on) 当设置为on的时候,会使用脚本去创建私钥和root证书去认证registry的toke
以下参数:
crt_country,
crt_state,
crt_location, 
crt_organization, 
crt_organizationalunit, 
crt_commonname, 
crt_email 
被用来省城key。设置为off的时候,key和root证书可以被应用在外部的源中。
以上信息引用自:https://my.oschina.net/xxbAndy/blog/786712
根据以上参数介绍,结合自己的环境可自行修改,当然你也可以在搭建完成后,通过web页面修改这些参数,一般线上环境建议使用域名方式访问,同时将默认密码更改。此处我先只更改以下一个参数:
# vim /opt/harbor/harbor.cfg
hostname = 192.168.162.54
3.更改docker配置,重启docker服务:
注意:因为harbor配置中默认使用http连接,而docker默认采用https方式连接,所以如果上面的配置文件中你采用默认参数“ui_url_protocol = http ”,Docker认为是不安全的,push镜像会报错,还需要修改docker配置,而关于harbor如何采用https方式连接,本文不做讨论。(其实,如果是公司内部自己使用,个人觉得没必要设置https方式)
# vim /usr/lib/systemd/system/docker.service  #添加--insecure-registry=ip地址
ExecStart=/usr/bin/dockerd --insecure-registry=192.168.162.54
# systemctl daemon-reload && systemctl restart docker
4、修改Harbor的Docker镜像存放路径
默认情况下,Harbor是把镜像存储在本地文件系统中的,存储在/data/registry目录下,映射到docker容器里面的/storage目录下。但是有时候我们想把镜像存储在本地空间较大的硬盘上,这时候就需要修改配置文件,这个参数是在/opt/harbor/docker-compose.yml文件中指定的,需要在执行install.sh脚本运行之前修改,例如我修改为/opt/data/registry目录(ps:无需提前创建此目录),操作如下图:
# cp /opt/harbor/docker-compose.yml{,.bak}
# vim /opt/harbor/docker-compose.yml
20170809151000
5.执行安装脚本并启动harbor服务:
# cd /opt/harbor/
# ./install.sh
✔ ----Harbor has been installed and started successfully.----

Now you should be able to visit the admin portal at http://192.168.162.54. 
For more details, please visit https://github.com/vmware/harbor .

输出如上信息代表启动正常,此时会启动几个Contianer,如下图:

20170810134601
之后如果想停止或启动harbor的话,可以使用如下命令:
停止:
# docker-compose stop
启动:
# docker-compose start
6、访问harbor界面
在浏览器访问栏直接输入该harbor.cfg中配置的hostname参数即可,默认用户密码是:admin/Harbor12345,如下图所示
 20170810133828

四、验证使用Harbor

 1、从docker hub上下载hello-world镜像
# docker run hello-world
2、给镜像打标签,名称格式(registryAddress[:端口]/项目/imageName[:tag],其中library是harbor默认提供的项目
# docker tag hello-world 192.168.162.54/library/hello-world
3、登录镜像私服
# docker login -u admin -p 'Harbor12345' 192.168.162.54
4、上传镜像
# docker push 192.168.162.54/library/hello-world
5、web登录验证
在浏览器上访问192.168.162.54,登录完成后,点击library这个项目,即可看到上传的hello-world,如下图
20170810155618

至此基于http访问方式的harbor服务搭建完毕!

 来源: http://www.jiagoumi.com/work/1221.html

搭建安全的docker private registry v2指南(Let’s Encrypt)

本站已实现https访问,访问地址:https://deepzz.com

权威Registry

获取安全证书有两个办法:互联网认证的CA处获取。自建CA自己给自己签名。

  • 1、从认证CA处获取签名证书,大多数是需要付出一定费用的,近些年也有认证CA提供免费证书,例如Let’s Encrypt(被大多数浏览器信任)。下文使用Let’s Encrypt的例子您将清楚地看到这个步骤。
  • 2、自建CA并签名证书的方式所带来的问题是CA本身的维护以及客户端方面的维护。要保证自建CA的安全需要有比较扎实的基础安全知识,维护它的运转需要有对签名流程进行干预的控制能力,或自动、或手工。客户端方面,同样需要对所有客户端按照其CA安装机制来进行额外安装。若将自建CA维护到与认证CA同等的安全性和便利性,所付出的代价将超过付费证书。因此这种方式主要用于试验性环境。

LetsEncrypt证书

1、准备一台服务器(有公网IP),已做好域名解析。这里以Ubuntu 14.04 TLS为例。
2、确保该服务器80,443端口可以从互联网访问到且不被占用(关掉占用端口的服务器)。

因为LetsEncrypt申请证书是需要联网签名的,并且要用到80端口。

在成功获取证书后,服务器IP和端口就可另作他用。因此,可以在某台有公网IP的主机服务器上获取证书,再将证书转移到其它服务器进行使用。若采用这样的方式,Docker客户端需要将私网IP和dockie.mydomain.com对应写入hosts文件或将该解析写到私网DNS服务器里。但证书到期renew的时候还需要同样的公网域名(公网IP可以不同)。

3、在服务器上获取签名证书

SH$ git clone https://github.com/letsencrypt/letsencrypt.git
$ cd letsencrypt
$ sudo ./certbot-auto certonly --standalone --email admin@example.com -d example.com -d www.example.com -d other.example.net

这里直接根据官方提供的方法从GITHUB获取安装包和目录安装,上面是一个标准的格式,根据我们的邮箱、以及需要添加的域名设置,如果多域名直接 在后面添加-d就可以,比如继续添加其他域名 -d www.laojiang.me -d laojiang.me以此类推。

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
  /etc/letsencrypt/live/laojiang.me/fullchain.pem. Your cert will
  expire on 2016-07-13. To obtain a new version of the certificate in
  the future, simply run Let's Encrypt again.
- If you like Let's Encrypt, please consider supporting our work by:
Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le

看到这样的文字和提示就代表获取Let’s Encrypt证书成功,时间是90天,我们需要在到期前手手动续约就可以继续90天。然后我们在”/etc/letsencrypt/live/域名/“目录中看到4个文件(cert.pem chain.pem fullchain.pem privkey.pem)。

4、更新证书
使用下面这条命令,更新证书,它将更新到期时间不到30天的证书,而且它会根据你当初生成证书的设置更新你的证书。

$ ./certbot-auto renew --dry-run

5、通过钩子更新证书

$ ./certbot-auto renew --standalone --pre-hook "service nginx stop" --post-hook "service nginx start"

这里使用了一个钩子,--pre-hook>更新前执行命令命令,--post-hook更新之后执行命令。

自签名证书

执行以下命令,它会在文件夹下生成domain.key和domain.crt

SHmkdir -p certs && openssl req \
 -newkey rsa:4096 \
 -nodes -sha256 \
 -keyout certs/domain.key \
 -x509 -days 365 \
 -out certs/domain.crt

相关参数说明:

SHCountry Name (2 letter code) [AU]:CN                               #国家代码,中国CN
State or Province Name (full name) [Some-State]:Sichuan            #省份全拼
Locality Name (eg, city) []:Chengdu                                #城市
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Person  #组织名,公司名
Organizational Unit Name (eg, section) []:Chen                     #部门名称
Common Name (e.g. server FQDN or YOUR name) []:registry.domain.com #这里必须填写Docker Registry使用的域名
Email Address []:ccc@domain.com                                    #电子邮件

自签名证书,使用Docker Registry的Docker机需要将domain.crt拷贝到 /etc/docker/certs.d/[docker_registry_domain]/ca.crt,然后重启docker,将domain.crt内容放入系统的CA bundle文件当中,使操作系统信任我们的自签名证书。

CentOS 6 / 7中bundle文件的位置在/etc/pki/tls/certs/ca-bundle.crt:

cat domain.crt >> /etc/pki/tls/certs/ca-bundle.crt

Ubuntu/Debian Bundle文件地址/etc/ssl/certs/ca-certificates.crt

cat domain.crt >> /etc/ssl/certs/ca-certificates.crt

Mac

1、点击钥匙串访问
2、点击系统
3、点击证书
4、将domain.crt拖到目录下
5、输入密码,添加成功
6、双击该证书,点击信任,选择
7、退出

安装docker

详细步骤请跳转:docker 安装、配置步骤

搭建Docker registry

创建certs目录:

$ cd ~
$ mkdir -p certs

复制或者添加你的证书文件到certs/domain.cert,你的私钥文件到certs/domain.key

SH# Let's Encrypt证书
$ sudo cp /etc/letsencrypt/live/registry.domain.com/fullchain.pem ~/certs/domain.cert
$ sudo cp /etc/letsencrypt/live/registry.domain.com/privkey.pem ~/certs/domain.key
# 自签名证书,直接复制文件夹到 ~/certs

获取registry镜像

$ sudo docker pull registry:2

一切准备就绪,运行registry:

SH$ sudo docker run -d -p 5000:5000 --restart=always --name registry \
    -v /data/registry:/var/lib/registry \
    -v ~/certs/:/certs \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.cert \
    -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
    -e REGISTRY_STORAGE_DELETE_ENABLED=true \
    registry:2

测试registry是否启动成功:

SH$ docker ps                                            #你可以查看运行了那些容器
$ telnet dockie.mydomain.com 5000                      #查看能否连接成功
$ curl -i -k -v https://registry.mydomain.com:5000     #使用curl来测试TLS是否工作正常

浏览器访问https://registry.mydomain.com:5000,可以看到该连接可以安全访问了。

你现在通过其它docker主机应该能够访问你的registry:

SH$ docker pull ubuntu
$ docker tag ubuntu myregistrydomain.com:5000/ubuntu
$ docker push myregistrydomain.com:5000/ubuntu
$ docker pull myregistrydomain.com:5000/ubuntu

实现访问限制

最简单的方法是通过basic authentication。
首先,创建密码文件。你需要替换这两个参数,用户名:testuser,密码:testpasswd。

SH$ cd ~
$ mkdir auth
$ docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/htpasswd

然后,停止你的registry,之后,用下面的代码再次启动:

SHdocker run -d -p 5000:5000 --restart=always --name registry \
  -v /data/registry:/var/lib/registry \
  -v ~/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v ~/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  registry:2

现在,你可以:

docker login registry.domain.com:5000

然后,然后,你就可以通过该user进行push和pull操作了。

移除 Registry

使用 -v 来删除容器卷。

$ docker stop registry && docker rm -v registry

本文链接:https://deepzz.com/post/secure-docker-registry.html,参与评论 »

--EOF--

超详细记录公司多用户Docker仓库创建安全认证和应用

概述:超详细记录建立公司内部多用户Docker仓库,自定义CA证书,https安全认证。服务器作为远程Docker仓库,其他开发端(如server2,server3等)添加认证并登录,多开发端可以上传下载公司内部的docker仓库的镜像。公司的CI,CD用内部docker镜像仓库上传和下载方便,安全,方便统一管理公司容器镜像。

默认Docker在服务器端和开发端已经安装完毕,若没有,可参考我另一篇博文Ubuntu16.04安装Docker1.12+开发实例+hello world+web应用容器。

1.服务器端(server1)操作。下载Docker仓库镜像,创建CA证书,创建docker仓库。

1.1.下载docker镜像

docker pull registry:2

1.2.在服务器端创建自定义签发的CA证书

mkdir -p ~/docker/certs && openssl req \
  -newkey rsa:4096 -nodes -sha256 -keyout ~/docker/certs/domain.key \
  -x509 -days 365 -out ~/docker/certs/domain.crt

输出如下信息:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:rz
Organizational Unit Name (eg, section) []:rz
Common Name (e.g. server FQDN or YOUR name) []:wangxiaolei.com     
Email Address []:wov@outlook.com

注意自定域名,如wangxiaolei.comCommon Name (e.g. server FQDN or YOUR name) []:wangxiaolei.com

1.3.添加多用户信息,创建仓库的用户名,密码。

  • a.docker仓库添加用户的登录用户名和密码。
mkdir -p ~/docker/auth
docker run --entrypoint htpasswd registry:2 -Bbn wangxiaolei 123456 >>~/docker/auth/htpasswd
  • b.docker仓库添加多位开发人员信息。
docker run --entrypoint htpasswd registry:2 -Bbn wangxiaolei1 123456 >>~/docker/auth/htpasswd
docker run --entrypoint htpasswd registry:2 -Bbn wangxiaolei2 123456 >>~/docker/auth/htpasswd
docker run --entrypoint htpasswd registry:2 -Bbn wangxiaolei3 123456 >>~/docker/auth/htpasswd

1.4.重启docker服务

sudo service docker restart

1.5.创建registry容器

docker run -d -p 5000:5000 --restart=always --name registry \
  -v ~/docker/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -v ~/docker/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

1.6.通过sftp或者scp将远程仓库服务器端的docker.crt下载到开发端(如用户xiaolei的开发端)

scp ~/docker/certs/domain.crt xiaolei@192.168.148.239:~

2.多客户端操作。CA授信,登录创建好的远程docker仓库(server2或server3等等,都进行如下操作即可)。

2.1.将1.6步骤的domain.crt放到docker的对应位置。

  • ubuntu系统
sudo mkdir -p ~/certs.d/wangxiaolei.com:5000
sudo cp  ~/domain.crt /etc/docker/certs.d/wangxiaolei.com:5000/ca.crt
  • redhat系统
cp ~/domain.crt /usr/local/share/ca-certificates/myregistrydomain.com.crt

2.2.登录远程docker仓库

  • 2.2.1.将域名和服务器ip映射(如果是真实能访问绑定的域名则省略此步骤)
sudo vim /etc/hosts
#在/etc/hosts添加如下内容
192.168.0.133 wangxiaolei.com
  • 2.2.2.登录远程Docker仓库
docker login wangxiaolei.com:5000

2.3.从官网上下载alpine镜像,标记然后推送到刚刚创建好的docker远程仓库中。

  • 2.3.1.官网仓库下载alpine镜像 docker pull alpine
  • 2.3.2.创建新的镜像(打标签) docker tag alpine wangxiaolei.com:5000/alpine:v1 其中,
    • tag为标签操作。
    • alpine为已经存在的alpine镜像,默认版本为latest。
    • wangxiaolei.com为域名,5000为端口。
    • alpine为自定义的镜像名称,v1为自定义的版本号。
  • 2.3.3.上传新创建的镜像到自己的远程docker仓库 docker push wangxiaolei.com:5000/alpine:v1

2.4.其他内部开发人员可以使用 docker pull wangxiaolei.com:5000/alpine:v1下载alpine镜像

3.查看docker仓库上有哪些镜像。

3.1.此时,登入https://wangxiaolei.com:5000/v2/_catalog

3.2.输入开发人员的信息,用户名和密码

3.3.查看内部Docker仓库中已有alpine的镜像

3.4.相关参考文档

  • Docker安装教程:Ubuntu16.04安装Docker1.12+开发实例+hello world+web应用容器
  • Docker官方文档1:Deploying a registry server
  • Docker官方文档2:Using self-signed certificates
  • Docker官方文档3:Docker Registry HTTP API V2

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

来源:https://cloud.tencent.com/developer/article/1010804