0%

DevOps运维开发

Docker Machine

简介

  • Docker MachineDocker官方编排(Orchestration)项目之一,负责在多种平台上快速安装Docker环境Docker Machine项目基于Go语言实现,目前在Github上进行维护.用Docker Machine可以批量安装和配置docker host,这个host可以是本地的虚拟机,物理机,也可以是公有云中的云主机.Docker Machine支持在不同的环境下安装配置docker host,包括:
    • (1) 常规Linux操作系统.
    • (2) 虚拟化平台—VirtualBox,VMWare,Hyper-V,OpenStack.
    • (3) 公有云— Amazon Web Services,Microsoft Azure,Google Compute Engine,Digital Ocean等.
  • Docker Machine为这些环境起了一个统一的名字:provider.对于某个特定的provider,Docker Machine使用相应的driver安装和配置
    docker host.

脚本安装

1
2
3
4
5
6
7
8
9
10
# 安装
~$ base=https://github.com/docker/machine/releases/download/v0.16.0 &&
curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
sudo install /tmp/docker-machine /usr/local/bin/docker-machine
# 查看版本
~$ docker-machine version
docker-machine version 0.16.0, build 702c267f
# 列出主机列表
~$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS

创建Machine

  • 下面命令就会在本机的VirtualBox里创建一个名为default的虚拟机.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    $ docker-machine  create -d virtualbox default
    Running pre-create checks...
    Creating machine...
    (default) Copying /home/lcy/.docker/machine/cache/boot2docker.iso to /home/lcy/.docker/machine/machines/default/boot2docker.iso...
    (default) Creating VirtualBox VM...
    (default) Creating SSH key...
    (default) Starting the VM...
    (default) Check network to re-create if needed...
    (default) Waiting for an IP...
    Waiting for machine to be running, this may take a few minutes...
    Detecting operating system of created instance...
    [...]
    Docker is up and running!
    To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env default
    ~$ docker-machine create -d virtualbox manager1 &&
    > docker-machine create -d virtualbox manager2 &&
    > docker-machine create -d virtualbox worker1 &&
    > docker-machine create -d virtualbox worker2
    ~$ docker-machine ls
    NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
    default - virtualbox Running tcp://192.168.99.100:2376 v18.09.1
    manager1 - virtualbox Running tcp://192.168.99.101:2376 v18.09.1
    manager2 - virtualbox Running tcp://192.168.99.102:2376 v18.09.1
    worker1 - virtualbox Running tcp://192.168.99.103:2376 v18.09.1
    worker2 - virtualbox Running tcp://192.168.99.104:2376 v18.09.1

Docker端的操作

1
2
# 更新worker1,worker2的docker到最新版本,可以指执行.
~$ docker-machine upgrade worker1 worker2
  • 为了支持ansible管理操作,下面安装一些python环境相关的软件.参考链接.tce的安装目录是docker@manager1:/usr/local/tce.installed,比如:要先删除python旧的安装的命令:docker-machine ssh manager1 "rm -rf /usr/local/tce.installed/python",再用下面命令重新安装.这里使用的bash脚本的for循环串行处理,如果要并行处理,可以参考parallel.

安装python环境包

1
~$  for item in manager1 manager2 worker1 worker2; do docker-machine ssh $item "tce-load -wi python && curl https://bootstrap.pypa.io/get-pip.py | sudo python - && sudo ln -s /usr/local/bin/python /usr/bin/python";done

Ansible管理连接

  • 创建主机文件,因为每一个主机的私钥位置不同.所以在hosts.txt中具体指定如下.

    1
    2
    3
    4
    5
    6
    7
    ~$ cat hosts.txt
    [swarm]
    192.168.99.100 ansible_ssh_private_key_file=/home/lcy/.docker/machine/machines/default/id_rsa ansible_python_interpreter=/usr/local/bin/python
    192.168.99.101 ansible_ssh_private_key_file=/home/lcy/.docker/machine/machines/manager1/id_rsa ansible_python_interpreter=/usr/local/bin/python
    192.168.99.102 ansible_ssh_private_key_file=/home/lcy/.docker/machine/machines/manager2/id_rsa ansible_python_interpreter=/usr/local/bin/python
    192.168.99.103 ansible_ssh_private_key_file=/home/lcy/.docker/machine/machines/worker1/id_rsa ansible_python_interpreter=/usr/local/bin/python
    192.168.99.104 ansible_ssh_private_key_file=/home/lcy/.docker/machine/machines/worker2/id_rsa ansible_python_interpreter=/usr/local/bin/python
  • 连接测试.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ~$ ansible -i hosts.txt all -u docker -m ping
    192.168.99.102 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    192.168.99.100 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    192.168.99.103 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    192.168.99.104 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    192.168.99.101 | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }

配置Docker Swarm集群节点

配置Swarm管理节点

1
2
3
4
5
6
7
8
~$ docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.99.101"
Swarm initialized: current node (slf4m19dsk0cvo6wcpxjwm10v) is now a manager.

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

docker swarm join --token SWMTKN-1-4lwpkgvw8lqn68k20n89qy39uvhdx4u6cznak5zy3q6sp5nlp3-dsf3agxhdq6prycves2cxg16w 192.168.99.101:2377

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

配置工作节点

  • worker1,worker2创建成工作节点,并加入到集群中.
    1
    2
    3
    4
    5
    ~$ docker-machine ssh worker1 "docker swarm join --token SWMTKN-1-4lwpkgvw8lqn68k20n89qy39uvhdx4u6cznak5zy3q6sp5nlp3-dsf3agxhdq6prycves2cxg16w 192.168.99.101:2377"
    This node joined a swarm as a worker.

    ~$ docker-machine ssh worker2 "docker swarm join --token SWMTKN-1-4lwpkgvw8lqn68k20n89qy39uvhdx4u6cznak5zy3q6sp5nlp3-dsf3agxhdq6prycves2cxg16w 192.168.99.101:2377"
    This node joined a swarm as a worker.

添加备用管理节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看加入swarm集群管理节点的token
~$ docker-machine ssh manager1 "docker swarm join-token manager"
To add a manager to this swarm, run the following command:

docker swarm join --token SWMTKN-1-4lwpkgvw8lqn68k20n89qy39uvhdx4u6cznak5zy3q6sp5nlp3-1pg2xuizss0074mw3xgf59b5t 192.168.99.101:2377
# 把manager2加入swarm管理节点,做为备用候选管理节点
~$ docker-machine ssh manager2 "docker swarm join --token SWMTKN-1-4lwpkgvw8lqn68k20n89qy39uvhdx4u6cznak5zy3q6sp5nlp3-1pg2xuizss0074mw3xgf59b5t 192.168.99.101:2377"
This node joined a swarm as a manager.
# 查看swarm集群节点信息.
~$ docker-machine ssh manager1 "docker node ls"
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
slf4m19dsk0cvo6wcpxjwm10v * manager1 Ready Active Leader 18.09.1
5navxdx9kkvph4elfb2dcuiee manager2 Ready Active Reachable 18.09.1
wsvs8cb6sbroj0wuz09z9vrdj worker1 Ready Active 18.09.1
qkwz8akr2ef8oe5kddibmglfs worker2 Ready Active 18.09.1

创建docker私有仓库

  • 通过下命令在本机创建一个私有的镜像仓库.

    1
    2
    3
    4
    5
    6
    7
    8
    ~$ docker run -d -v /data/docker-registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry
    Unable to find image 'registry:latest' locally
    latest: Pulling from library/registry
    cd784148e348: Pull complete
    [...]
    Digest: sha256:a54bc9be148764891c44676ce8c44f1e53514c43b1bfbab87b896f4b9f0b5d99
    Status: Downloaded newer image for registry:latest
    242af2d15586d2d571c46c5edf821ce958cf22139d957e52a6f5d959726957bf
  • 接下来,将本地已有的镜像文件推送到刚才新建的仓库中去.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    ~$ docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    242af2d15586 registry "/entrypoint.sh /etc…" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp registry
    8ee3d7fb435f redis "docker-entrypoint.s…" 4 months ago Up 3 hours 0.0.0.0:6379->6379/tcp redis
    608b60a022e8 postgres:9.6 "docker-entrypoint.s…" 4 months ago Up 3 hours 0.0.0.0:5432->5432/tcp pg96

    # 把本地的postgres:9.6版本的镜像,改成192.168.99.1:5000/postgres:v3标签
    ~$ docker tag postgres:9.6 192.168.99.1:5000/postgres:v3
    docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    registry latest 116995fd6624 5 days ago 25.8MB
    127.0.0.1:5000/postgres 9.6 0178d5af9576 5 months ago 229MB
    192.168.99.1:5000/postgres 9.6 0178d5af9576 5 months ago 229MB
    postgres 9.6 0178d5af9576 5 months ago 229MB
    # 推送镜像.
    ~$ docker push 192.168.99.1:5000/postgres:v3
    The push refers to repository [192.168.99.1:5000/postgres]
    10cb36af78fe: Pushed
    [...]
    v3: digest: sha256:86a7984760c1d36c7c9ebec73706f05d76e7615937a45ae0d110b2112fd5cbfa size: 3245
    ~$ curl http://192.168.99.1:5000/v2/_catalog
    {"repositories":["postgres"]}
    ~$ curl http://192.168.99.1:5000/v2/postgres/tags/list
    {"name":"postgres","tags":["v3"]}
  • 简单的从公网下载镜推进私有库中.

    1
    2
    3
    4
    5
    ~$ docker pull dockersamples/visualizer
    ~$ docker tag dockersamples/visualizer 192.168.99.1:5000/visualizer:v4
    ~$ docker push 192.168.99.1:5000/visualizer:v4
    ~$ curl http://192.168.99.1:5000/v2/_catalog
    {"repositories":["postgres","visualizer"]}

- 通过 ansible 命令,在4个 hosts 节点中的 docker 启动参数中加入前面创建的私有仓库地址.

1
2
3
~$ ansible -i hosts.txt all -u docker -b  -m lineinfile -a "path=/etc/docker/daemon.json line='{\n\t\t\"insecure-registries\":    [\"192.168.99.1:5000\"]\n}' create=yes"
# 重启所有节点
~$ docker-machine restart manager1 manager2 worker2 worker1

Docker Service部署单个集群服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
~$ docker-machine ssh manager1 "docker service create --replicas 4 -p 15432:5432 --name pgsql 192.168.99.1:5000/postgres:v3"
yt4u3vmyq3gp9pc2bgowti1lf
overall progress: 0 out of 4 tasks
[....]
verify: Service converged

~$ docker-machine ssh manager1 "docker service ls"
ID NAME MODE REPLICAS IMAGE PORTS
yt4u3vmyq3gp pgsql replicated 4/4 192.168.99.1:5000/postgres:v3 *:15432->5432/tcp
~$ docker-machine ssh manager1 "docker service ps pgsql"
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
zj09wnhy4utz pgsql.1 192.168.99.1:5000/postgres:v3 worker1 Running Running 27 seconds ago
l7feljripf38 pgsql.2 192.168.99.1:5000/postgres:v3 manager2 Running Running 27 seconds ago
omxdx1cw8c7x pgsql.3 192.168.99.1:5000/postgres:v3 worker2 Running Running 27 seconds ago
tkghl3px2l08 pgsql.4 192.168.99.1:5000/postgres:v3 manager1 Running Running 26 seconds ago

# 登录测试一下
~$ psql -h 192.168.99.101 -p 15432 -U postgres -W
Password for user postgres:
psql (10.6 (Debian 10.6-1.pgdg90+1), server 9.6.11)
Type "help" for help.

Docker Stack部署多个集群服务

  • 确保下列的image是在本的仓库中找得到的.确认镜像

    1
    2
    3
    4
    ~$ docker images | awk '$2 ~/v4/ {print}'
    192.168.99.1:5000/nginx v4 42b4762643dc 34 hours ago 109MB
    192.168.99.1:5000/visualizer v4 f6411ebd974c 3 weeks ago 166MB
    192.168.99.1:5000/portainer v4 a01958db7424 6 weeks ago 72.2MB
  • docker-compose.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    version: '3'

    services:
    nginx:
    image: 192.168.99.1:5000/nginx:v4
    ports:
    - 8088:80
    deploy:
    mode: replicated
    replicas: 4

    visualizer:
    image: 192.168.99.1:5000/visualizer:v4
    ports:
    - '8080:8080'
    volumes:
    - '/var/run/docker.sock:/var/run/docker.sock'
    deploy:
    replicas: 1
    placement:
    constraints: [node.role == manager]

    portainer:
    image: 192.168.99.1:5000/portainer:v4
    ports:
    - '9000:9000'
    volumes:
    - '/var/run/docker.sock:/var/run/docker.sock'
    deploy:
    replicas: 1
    placement:
    constraints: [node.role == manager]

创建服务

1
2
3
4
5
~$ docker-machine ssh manager1 "docker stack deploy -c docker-compose.yml deploy-demo"
Creating network deploy-demo_default
Creating service deploy-demo_visualizer
Creating service deploy-demo_portainer
Creating service deploy-demo_nginx

管理阿里云ECS

阿里云官方驱动

  • 阿里云 Docker Machine 驱动
  • 阿里云 ECS Docker Machine Driver 入门指南
  • 按照上述在本地的VirtualBox创建主机的类比,使用阿里云官方的驱动,需要阿里的的安全秘钥以及对应的Region信息.如果想创建VPC网络,还需要有
    VPC IDVSwitch ID.操作起稍显麻烦,而且--aliyunecs-access-key-id,--aliyunecs-access-key-secret这两个参数权限是相当重要,这个只在以后工作的具体应用中有使用需要时,再去了解它的功能.

generic驱动

  • 下面虽然没有阿里云driver但有一个generic driver,可通过ssh管理现有的机器,原则上所有的Linux机器都支持.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ~$ docker-machine create --driver generic --generic-ip-address DB001 --generic-ssh-user lcy  --generic-ssh-key $HOME/.ssh/id_rsa   aliyun-machine
    Running pre-create checks...
    Creating machine...
    (aliyun-machine) Importing SSH key...
    Waiting for machine to be running, this may take a few minutes...
    Detecting operating system of created instance...
    Waiting for SSH to be available...
    Detecting the provisioner...
    Provisioning with debian...
    Copying certs to the local machine directory...
    Copying certs to the remote machine...
    Setting Docker configuration on the remote daemon...
    Checking connection to Docker...
    Docker is up and running!
    To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env aliyun-machine
    ~$ docker-machine env aliyun-machine
    export DOCKER_TLS_VERIFY="1"
    export DOCKER_HOST="tcp://DB001:2376"
    export DOCKER_CERT_PATH="/home/lcy/.docker/machine/machines/aliyun-machine"
    export DOCKER_MACHINE_NAME="aliyun-machine"
    # Run this command to configure your shell:
    # eval $(docker-machine env aliyun-machine)

错误

  • 要在/etc/docker/daemon.json加入{ "insecure-registries": ["192.168.99.1:5000"] }这一行,不然会出现下面的错误.

    1
    2
    ~$ docker pull 192.168.99.1:5000/postgres:9.6
    Error response from daemon: Get https://192.168.99.1:5000/v2/: http: server gave HTTP response to HTTPS client
  • ansible连接到boot2docker镜像无python环境的错误

    1
    2
    3
    4
    5
    6
    7
    192.168.99.102 | FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to 192.168.99.102 closed.\r\n",
    "module_stdout": "/bin/sh: /usr/local/bin/python: not found\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 127
    }

Ansible

安装

1
~$ pip install ansible ansible-lint

命令格式

  • ansible <host-pattern> [options],Inventory中定义的主机或主机组,可以为ip,hostname,Inventory中的group组名,具有".","\*".":"等特殊字符的匹配型字符串.<>;表示为必须参数,\[\]表示为可选参数.
  • 比如使用apt模块,root用户,更新系统的命令.后面会讲基于YMAL格式的配置文件.
    1
    ~$ ansible -i ~/.ansible/hosts all -u root -m apt -a "upgrade=yes update_cache=yes cache_valid_time=86400"
  • 下例使用authorized_key模块为用户添加公钥匙,exclusive=True就为替换现有的 key.下例为:在原有的 key 附加新的 key.
    1
    2
    3
    ~$ ansible -i ~/.ansible/hosts all -u lcy -m authorized_key -a "user=lcy state=present  key='ssh-rsa AAAAB3NzaC1yc...... user@gentoo'"
    # 在主机的hosts添加
    ~$ ansible -i ~/.ansible/hosts all -u lcy -b -m lineinfile -a "path=/etc/hosts create=yes line='127.0.0.1\tlocalhost\n172.18.127.186\tDB001\n172.18.192.77\tWeb001\n172.18.253.222\tFE001\n172.18.192.76\tDIG001'"

查看系统信息

1
2
3
4
5
6
7
# 这里是调用command这个模块,运行系统命令.
~$ ansible -i ~/.ansible/hosts Web001 -u root -m command -a 'lsb_release -a'
120.77.xxx.xx | CHANGED | rc=0 >>
Distributor ID: Debian
Description: Debian GNU/Linux 9.6 (stretch)
Release: 9.6
Codename: stretchNo LSB modules are available.

命令工具

ansible-doc

  • 使用ansible-doc可以查看所有支持的模块文档,因为我这里使用的是Debian,这里把它相关的包管理模块列出来.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ~$ ansible-doc  -l | grep "apt"
    apt Manages apt-packages
    apt_key Add or remove an apt key
    apt_repository Add and remove APT repositories
    apt_rpm apt_rpm package manager
    na_ontap_ucadapter NetApp ONTAP UC adapter configuration
    nios_naptr_record Configure Infoblox NIOS NAPTR records

    # 可以查该模块的参数与使用示例.也可以打开网页文档[apt_module](https://docs.ansible.com/ansible/latest/modules/apt_module.html)
    ~$ ansible-doc apt
    > APT (/home/lcy/.pyenv/versions/3.6.6/envs/py3dev/lib/python3.6/site-packages/ansible/modules/packaging/os/apt.py)

    Manages \`apt\' packages (such as for Debian/Ubuntu).

    OPTIONS (= is mandatory):

    - allow_unauthenticated
    Ignore if packages cannot be authenticated. This is useful for bootstrapping environments that manage their own apt-key setup.
    \`allow_unauthenticated\' is only supported with state: \`install\'/\`present\'
    [Default: no]
    type: bool
    version_added: 2.1
    [....]

ansible-playbook

  • Ansiable的任务配置文件被称为Playbook,可以称之为”剧本”,Playbook具有编写简单,可定制性高,灵活方便,以及可固化日常所有操作的特点.在下面的docker 安装用一个真实的完整实例演示.

配置

  • 默认配置文件名为ansible.cfg,它可以存在于很多地方,默认是/etc/ansible.cfg与用户目录下的~/.ansible/ansible.cfg.Ad-Hoc,Ansible-playbook,前者是临时命令的执行,后者是Ad-Hoc的集合,相当于是一个脚本.
  • 下面是一个经典的hosts文件,它默认找的位置是/etc/ansible/hosts,这里是用户目录.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    ~$ cat ~/.ansible/hosts
    [Web001]
    120.77.xxx.xx

    [DB001]
    119.23.xx.xxx

    [DIG001]
    120.78.xx.xxx

    [FE001]
    112.74.xxx.xx

    ~$ ansible -i ~/.ansible/hosts all -m ping -u root
    120.77.xxx.xx | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    119.23.xx.xxx | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    112.74.xx.xxx | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }
    120.78.xxx.xx | SUCCESS => {
    "changed": false,
    "ping": "pong"
    }

ansible-vault

  • ansible-vault主要用于配置文件加密,如编写要的Playbook配置文件里包含敏感信息.参考这里
1
2
3
4
5
6
7
8
9
# 加密后的a.yaml打开全是乱码.
~$ ansible-vault encrypt a.yaml
New Vault password:
Confirm New Vault password:
Encryption successful
# 解密a.yaml
~$ ansible-vault decrypt a.yaml
Vault password:
Decryption successful

ansible-galaxy

  • Ansible Galaxy 文档

  • 这个跟三星手机没有任何关系 ,可以把它简单地理解为github或者pip的功能.主要是用来生成,查找,安装一些优秀的Roles.一些优质的Roles可以在这里找到.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    ~$  ansible-galaxy --help
    Usage: ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ...

    Perform various Role related operations.

    Options:
    -h, --help show this help message and exit
    -c, --ignore-certs Ignore SSL certificate validation errors.
    -s API_SERVER, --server=API_SERVER
    The API server destination
    -v, --verbose verbose mode (-vvv for more, -vvvv to enable
    connection debugging)
    --version show program's version number and exit

    See 'ansible-galaxy <command> --help' for more information on a specific
    command.
  • 安装postgresql Roles,以及它的目录结构.如果要创建自定义的Roles,可以参考这些结构.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    ~$ ansible-galaxy install geerlingguy.postgresql
    - downloading role 'postgresql', owned by geerlingguy
    - downloading role from https://github.com/geerlingguy/ansible-role-postgresql/archive/1.4.5.tar.gz
    - extracting geerlingguy.postgresql to /home/lcy/.ansible/roles/geerlingguy.postgresql
    - geerlingguy.postgresql (1.4.5) was installed successfully
    ~$ tree /home/lcy/.ansible/roles/geerlingguy.postgresql/
    /home/lcy/.ansible/roles/geerlingguy.postgresql/
    ├── defaults
    │ └── main.yml
    ├── handlers
    │ └── main.yml
    ├── LICENSE
    ├── meta
    │ └── main.yml
    ├── molecule
    │ └── default
    │ ├── molecule.yml
    │ ├── playbook.yml
    │ ├── tests
    │ │ └── test_default.py
    │ └── yaml-lint.yml
    ├── README.md
    ├── tasks
    │ ├── configure.yml
    │ ├── databases.yml
    │ ├── initialize.yml
    │ ├── main.yml
    │ ├── setup-Debian.yml
    │ ├── setup-RedHat.yml
    │ ├── users.yml
    │ └── variables.yml
    ├── templates
    │ ├── pg_hba.conf.j2
    │ └── postgres.sh.j2
    └── vars
    ├── Debian-7.yml
    ├── Debian-8.yml
    ├── Debian-9.yml
    ├── RedHat-6.yml
    ├── RedHat-7.yml
    ├── Ubuntu-14.yml
    ├── Ubuntu-16.yml
    └── Ubuntu-18.yml

    9 directories, 27 files

通过Ansiable安装docker

  • Serve Static Files by Nginx from Django using Docker
    - apt - Manages apt-packages - Get Docker CE for Debian - 这里参照Get Docker CE for Debian,把它的安装流程转换成一个Playbook文件来执行.这种安装方式,各个被安装的目标主机间的 docker 是相互独立的,如果要把它们集合起来做编排,要使用Docker Machine.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    ---
    - name: 安装基础软件
    hosts: all
    become: yes
    # user: root 这里可以直接用root,但是关闭root远程登录后要使用sudo.
    tasks:
    # 参照文档 https://docs.ansible.com/ansible/latest/modules/apt_module.html
    - name: 更新并安装
    apt:
    name: ['apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', tmux]
    allow_unauthenticated: yes
    update_cache: yes

    # 这是另一种安装软件列表的方式
    - name: Install a list of packages
    apt:
    name: '{{ packages }}'
    update_cache: yes
    vars:
    packages:
    - git
    - rsync
    - gcc
    - dirmngr
    - bwn-ng
    - tmux
    - tree

    - name: 更新并安装 gnupg2
    apt:
    name: gnupg2
    allow_unauthenticated: no
    update_cache: yes

    # 参照文档 https://docs.ansible.com/ansible/latest/modules/apt_key_module.html?highlight=apt%20key
    - name: 添加新的公钥
    apt_key:
    url: https://download.docker.com/linux/debian/gpg
    state: present

    # 参考文档 https://docs.ansible.com/ansible/latest/modules/command_module.html#command-module
    - name: 读取系统发行版本号
    command: lsb_release -sc
    register: result

    # 参照文档 https://docs.ansible.com/ansible/latest/modules/apt_repository_module.html?highlight=add%20apt%20repository
    - apt_repository:
    repo: deb [arch=amd64] https://download.docker.com/linux/debian {{ result.stdout }} stable
    state: present
    filename: docker-ce

    # 安装docker-ce,docker-compose
    - name: 更新并安装 'docker-ce', ,'bridge-utils'
    apt:
    name: ['docker-ce', 'bridge-utils']
    allow_unauthenticated: yes
    update_cache: yes

    - name:
    command: uname -s
    register: vendor

    - name:
    command: uname -m
    register: arch

    # 安装最新版本的docker-compose,使用apt安装的版本很老.
    - name: 安装最新版本的docker-compose-1.23.2
    get_url:
    url: https://github.com/docker/compose/releases/download/1.23.2/docker-compose-{{ vendor.stdout }}-{{ arch.stdout }}
    dest: /usr/local/bin/docker-compose
    mode: 0755

    - name: 重启机器
    reboot:
    reboot_timeout: 3600
  • 重启之后,应该就可以用下面命令行查看docker信息了.

1
~$ ansible -i ~/.ansible/hosts all -u lcy  -m command -a "docker info"
  • 注意:如不安装bridge-utils并重启,docker无法启动,可能会出现如下错误.
    1
    2
    3
    4
    Dec 29 10:26:16 DB001 dockerd[20493]: time="2018-12-29T10:26:16.760508487+08:00" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
    Dec 29 10:26:16 DB001 dockerd[20493]: Error starting daemon: Error initializing network controller: Error creating default "bridge" network: package not installed
    Dec 29 10:26:16 DB001 systemd[1]: docker.service: Main process exited, code=exited, status=1/FAILURE
    Dec 29 10:26:16 DB001 systemd[1]: Failed to start Docker Application Container Engine.

添加用户与组

  • 关于与开启用户的sudo功能,有两种方法,一是可以修改远程主机的/etc/sudoers文件.可以参照这里 也可以使用复制替换的方法,参照这里.也可以把用户加进sudo组里.

  • 如果要每一个用户添加一个初始密码,可以参照这里.Linux 下可以使用mkpasswd命令,如果其它系统,可以使用passlib这个 python的包来替换.如要使用sudo不用密码,要添加NOPASSWORD关键字.

    1
    2
    3
    4
    5
    6
    7
    ~$ mkpasswd --method=sha-512
    Password:
    $6$5QYVZSmH7$FXQcAQ8FsjMVk0x.ATQgpFHhgImp7hdITMh7zAE.VeAkQYDzdFAOxx6jqVFOY.52nRW4a6SjzEUnK.JSh73W61

    ~$ python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
    Password:
    $6$J15B6vXoZeekBlVy$.F6PelDYQRCeqapZ2/V3BQ5IjJXCdhG4g5NgoeNvnGJqf1dValk38IDzBuMfmctLMgQ4llyzVT3WN4pYrIpmZ0
  • 下面是添加两个用户,并加入相关组,以及修改sshd_config的相关参数.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    ---
    - name: 添加用户
    hosts: all
    user: root
    tasks:
    - name: remove users
    user:
    name: '{{ item }}'
    state: absent # absent 表示移除,present 表示添加
    remove: yes
    with_items:
    - lcy
    - gavin_kou

    - name: add the user "{{ item }}"
    # 参考链接 https://docs.ansible.com/ansible/latest/modules/user_module.html?highlight=user
    user:
    name: '{{ item }}'
    append: yes
    groups: docker,sudo
    shell: /bin/bash
    state: present
    generate_ssh_key: yes
    ssh_key_bits: 2048
    # ssh_key_file: .ssh/id_rsa
    # 这里可以使用 with_items来做数组循环. https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html?highlight=with_items
    with_items:
    - lcy
    - gavin_kou

    - name: 复制本的公钥到远程用户下.
    # 参考链接 https://docs.ansible.com/ansible/latest/modules/authorized_key_module.html
    authorized_key:
    user: lcy
    state: present
    # exclusive: True
    key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}\n"

    - name: Set authorized key for user ubuntu copying it from current user
    # 参考链接 https://docs.ansible.com/ansible/latest/modules/authorized_key_module.html
    authorized_key:
    user: gavin_kou
    state: present
    key: "{{ lookup('file','~/.ansible/gavin.pub') }}\n"
    # 参考链接 https://docs.ansible.com/ansible/latest/modules/lineinfile_module.html?highlight=sudoers
    - lineinfile:
    path: /etc/sudoers
    state: present
    regexp: '^%sudo\s'
    line: '%sudo ALL=(ALL) NOPASSWD: ALL'
    validate: '/usr/sbin/visudo -cf %s'

    # 关闭ssh的root登录功能.所以运行完这个剧本就不能使用root用户执行第二次了.
    - lineinfile:
    path: /etc/ssh/sshd_config
    state: present
    regexp: '^PermitRootLogin\s'
    line: 'PermitRootLogin no'

    - lineinfile:
    path: /etc/ssh/sshd_config
    state: present
    regexp: '^#ClientAliveInterval\s'
    line: 'ClientAliveInterval 30'

    - lineinfile:
    path: /etc/ssh/sshd_config
    state: present
    regexp: '^#ClientAliveCountMax\s'
    line: 'ClientAliveCountMax 3'
    # 参考消息 https://docs.ansible.com/ansible/latest/modules/systemd_module.html
    - name: 重加载sshd
    systemd:
    name: sshd
    state: reloaded

Docker的图形界面

  • docker 哪些平台技术(3)

  • UI For Docker已经deprecated,还是使用Portainer.

  • Portainer

    1
    ~$  docker run -d -p 9000:9000 --privileged -v /var/run/docker.sock:/var/run/docker.sock --name web-ui uifd/ui-for-docker
  • Portainer是一个开源、轻量级Docker管理用户界面,基于Docker API,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能.功能十分全面,基本能满足中小型单位对容器管理的全部需求.

    1
    ~$ docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data  -v /etc/hosts:/etc/hosts --name portainer-ui portainer/portainer

添加其它Docker服务器到portainer

  • Protect the Docker daemon socketTLS链接参考这里.

  • Using the Portainer Agent

  • portainer添加外部Docker实例有三种模式,一种是dockerd -H tcp://192.168.xx.xx:2376,通过监听TCP socket方式.这里可以用通过TLS来保证安全.第二种就是在目标服务器上安装portaineragent.以上两种方法,创建TLS证书比较麻烦,安装agent会消耗一些资源.Docker18.09开始,客户端可以通过SSH访问:docker -H ssh://me@example.com ps,但是portainer不支持这种协议方式, 只支持两种协议:tcp://,unix://.

  • 下面介绍如何使用TLS证书连接远程的 Docker Engine.

    1
    2
    3
    4
    5
    6
    # 创建CA私钥
    ~$ openssl genrsa -aes256 -out ca.key 4096
    # 使和CA私钥创建CA证书.
    ~$ openssl req -new -x509 -days 365 -key ca.key -sha256 -out ca.pem
    # 创建服务器私钥匙
    ~$ openssl genrsa -out server.key 4096
  • 创建服务器CSR文件.注意CN(Common Name)如果是域名如:www.examples.com,则客户端必须过www.examples.com访问到该服务器.才能验证通过.TLS连接时,需要限制客户端的IP或者域名列表.可以用使用密钥扩展文件支持.如只允许127.0.0.1 和 192.168.1.100客户端访问.echo subhectAltName = IP:127.0.0.1,IP:192.168.1.100 > allowips.cnf,在下面创建服务器证书命令后加上-extfile allowips.cnf就可以支持了.

1
2
3
4
5
6
~$ openssl req -subj "/CN=*" -sha256 -new -key server.key -out server.csr
~$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem
Signature ok
subject=CN = *
Getting CA Private Key
Enter pass phrase for ca.key:

- 创建客户端私钥与CSR

1
2
3
4
5
6
~$ openssl genrsa -out client.key 4096
~$ openssl req -subj "/CN=*" -new -key client.key -out client.csr

# 如果需要客户端的验证就加入下面的扩展.
~$ echo extendedKeyUsage = clientAuth > client.cnf
~$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem -extfile client.cnf
  • 运行服务端与客户端测试.为保证公钥文件安全,需要修改公钥匙文件的访问权限:chmod -v 0400 ca.key server.key client.key.防止证书被篡改:
    chmod -v 0444 ca.pem server.pem client.pem.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    ~$ tree
    .
    ├── ca.key
    ├── ca.pem
    ├── ca.srl
    ├── client.key
    ├── client.pem
    ├── server.key
    └── server.pem
    # 服务端运行
    ~$ sudo dockerd --tlsverify --tlscacert=ca.pem --tlscert=server.pem --tlskey=server.key -H tcp://0.0.0.0:2376
    # 客户端运行.这里必须使用主机名连接,所以上述portainer-ui容器运行,使用 -v /etc/hosts:/etc/hosts 选项.
    ~$ docker --tlsverify --tlscacert=ca.pem --tlscert=client.pem --tlskey=client.key -H tcp://<主机名>:2376 version
    # Docker 从 18.09 开始支持通过SSH访问,这个更安全更便捷.
    ~$ docker -H ssh://user@domain.com version
    Client:
    Version: 18.09.1
    API version: 1.39
    Go version: go1.10.6
    Git commit: 4c52b90
    Built: Wed Jan 9 19:35:59 2019
    OS/Arch: linux/amd64
    Experimental: false

    Server: Docker Engine - Community
    Engine:
    Version: 18.09.1
    API version: 1.39 (minimum version 1.12)
    Go version: go1.10.6
    Git commit: 4c52b90
    Built: Wed Jan 9 19:02:44 2019
    OS/Arch: linux/amd64
    Experimental: false

修改服务端systemd service

  • 带证书启动的docker进程可以按照上述的手动运行的形式,也可以通过修改系统的systemed来开启,把服务端的证书文件复制到/etc/docker/下面.方法如下:
    1
    2
    3
    4
    5
    6
    ~$ cat /lib/systemd/system/docker.service
    [...]
    #ExecStart=/usr/bin/dockerd -H fd://  这是原来默认的,只开放本地连接.
    ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server.pem --tlskey=/etc/docker/server.key -H tcp://0.0.0.0:2376 -H fd://
    [...]
    ~$ sudo systemctl daemon-reload #重新加载配置文件.

开启客户端默认证书模式

1
2
3
4
5
6
~$ mkdir -pv ~/.docker
~$ cp ca.pem ~/.docker
~$ cp client.key ~/.docker/key.pem # 一定要改这个名字
~$ cp client.pem ~/.docker/cert.pem # 一定要改这个名字
~$ export DOCKER_HOST=tcp://<HOST>:2376 DOCKER_TLS_VERIFY=1
~$ docker ps   # 证书模式连接

Docker错误

  • 如果出现如下的错误,要使用systemctl restart docker.service才能解决.
    1
    2
    docker: Error response from daemon: driver failed programming external connectivity on endpoint condescending_lalande (668389b4f87cc892fc233313eb738d0995c4080d3daabf28bf8c9bbe241a5434):  (iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.17.0.2 --dport 9000 -j ACCEPT: iptables: No chain/target/match by that name.
    (exit status 1)).

AnsibleDocker集成使用

  • 操作VOLUME

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ~$ docker volume create redis_vol
    ~$ docker volume inspect redis_vol
    [
    {
    "CreatedAt": "2019-01-09T17:28:44+08:00",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/redis_vol/_data",
    "Name": "redis_vol",
    "Options": {},
    "Scope": "local"
    }
    ]
    # 删除所有的卷
    ~$ docker volume prune
  • 必须安装docker-py,下面通过一个稍微复杂一点的例子来说明.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 如果是python3的话,有些模块会提示要换成安装: pip3 install docker
    ~$ pip install docker-py
    ~$ tree
    .
    ├── main.yaml
    ├── pgsql
    │ ├── file
    │ │ └── Dockerfile
    │ └── pgsql.yaml
    └── redis
    ├── file
    │ └── Dockerfile
    └── redis.yaml
  • main.yaml

    1
    2
    3
    4
    5
    6
    ---
    - hosts: DB001
    become: yes
    tasks:
    - include: pgsql/pgsql.yaml
    - include: redis/redis.yaml

Redis服务器

  • https://docs.docker.com/samples/library/redis/

  • https://github.com/docker-library/redis

  • Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 安装redis服务
    FROM debian:stretch
    # CMD echo "hello debian from Dockerfile."
    # https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-debian-9
    ENV DEBIAN_FRONTEND noninteractive

    RUN sed -i "s/deb.debian.org/mirrors.cloud.aliyuncs.com/g" /etc/apt/sources.list
    RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install redis-server
    # RUN sed -i 's/^appendonly no$/appendonly yes/g' /etc/redis/redis.conf
    # RUN sed -i 's/^daemonize yes$/daemonize no/g' /etc/redis/redis.conf
    EXPOSE 6379/tcp
    # CMD [ "/etc/init.d/redis-server start" ]
    USER root
    RUN rm -rf /data
    RUN mkdir /data && chown redis:redis -R /data
    VOLUME ["/data" ]
    RUN chown redis:redis -R /data
    CMD ["redis-server","/etc/redis/redis.conf"]
  • redis.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

- name: 创建WORKDIR
file:
path: workdir
state: directory
recurse: yes

- name: 上传Dockerfile到目标机的/tmp
# https://docs.ansible.com/ansible/latest/modules/synchronize_module.html?highlight=synchronize
synchronize:
src: redis/file/Dockerfile
dest: workdir

- name: Redis Server
# 参考地址 https://docs.ansible.com/ansible/latest/modules/docker_container_module.html?highlight=docker
docker_image:
name: redis
tag: v6
path: workdir
state: present

- name: 创建VOLUME的目录
# https://docs.ansible.com/ansible/latest/modules/file_module.html
become: yes
file:
path: ./redis-vol
state: directory
# 这里这了避免使用root运行docker,同时也避免使用root运行redis-server,把这个卷目录所有者改成docker里的redis的uid:gid的值,才能满足前述使用.这里为101
owner: 101
group: 101
recurse: yes

- name: create volume
# 这里使用 docker_volume 这个模块有问题,只能使下面的命令创建卷.创建卷不能指定路径,但是可以使用如: --opt type:ext4 --opt device=/dev/sdX 这个device必须是分区,块设备,不能是目录.
command: docker volume create redis_vol3

- name: Redis server
# 参考地址 https://docs.ansible.com/ansible/latest/modules/docker_container_module.html?highlight=docker
docker_container:
name: redis-server
# 对应上面创建的镜像.
image: 'redis:v6'
# command: redis-server --apendonly yes
state: started
recreate: yes
user: redis
# 设置密码登录,1234
command: redis-server --requirepass 1234 --appendonly yes --dir /data
published_ports:
- '6379:6379'
volumes:
- ./redis-vol:/data
  • 测试 Redis 服务.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
~$ redis-cli
127.0.0.1:6379> auth 1234
OK
127.0.0.1:6379> set dd 100
OK
127.0.0.1:6379> save # 写入磁盘.
OK
127.0.0.1:6379> exit

~$ redis-cli
127.0.0.1:6379> auth 1234
OK
127.0.0.1:6379> get dd
"100"
127.0.0.1:6379> config get dir # 查看系统的目录.
1) "dir"
2) "/data"
127.0.0.1:6379> quit

Postgresql数据库

  • 比较复杂的实例可以参考docker-postgresql,这个支持ENTRYPOINT参数,主从复制功能.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    ~$ cat Dockerfile
    # 参考这里 https://docs.docker.com/engine/examples/postgresql_service/#install-postgresql-on-docker
    FROM debian:stretch
    MAINTAINER lcy

    ENV DEBIAN_FRONTEND noninteractive
    # 添加这一行是为了避免下面的错误:
    # -----------------------------------------------
    # debconf: unable to initialize frontend: Dialog
    # debconf: (Dialog frontend will not work on a dumb terminal, an emacs shell buffer, or without a controlling terminal.)
    # debconf: falling back to frontend: Readline
    # debconf: unable to initialize frontend: Readline
    # debconf: (Can't locate Term/ReadLine.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7, <> line 19.)
    # debconf: falling back to frontend: Teletype
    # dpkg-preconfigure: unable to re-open stdin:
    #------------------------------------------------

    # RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
    # Add the PostgreSQL PGP key to verify their Debian packages.
    # It should be the same key as https://www.postgresql.org/media/keys/ACCC4CF8.asc
    # 这里因为部署在阿里云上,所以把软件仓库改成阿里云,加速下载,且免流量.
    RUN sed -i "s/deb.debian.org/mirrors.cloud.aliyuncs.com/g" /etc/apt/sources.list

    ENV PG_VERSION=10
    ENV PG_USER=postgres
    ENV PG_HOME=/var/lib/postgresql
    ENV PG_RUNDIR=/run/postgresql \
    PG_LOGDIR=/var/log/postgresql \
    PG_DATADIR=${PG_HOME}/${PG_VERSION}/main \
    PG_BINDIR=/usr/lib/postgresql/${PG_VERSION}/bin \
    PG_CONFIG=/etc/postgresql/${PG_VERSION}/main/postgresql.conf

    # 下面两个是必需安装才能,才能用apt-key添加公钥
    RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y apt-utils dirmngr gnupg2

    # CMD ["ping","-c","5","p80.pool.sks-keyservers.net"] 这里有可能会运行失败,如:读不到数据,没有解析的域名地址等.
    RUN apt-key adv --no-tty --keyserver ipv4.pool.sks-keyservers.net --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8

    # Add PostgreSQL's repository. It contains the most recent stable release
    # of PostgreSQL, ``10``.
    RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" > /etc/apt/sources.list.d/pgdg.list

    # Install ``python-software-properties``, ``software-properties-common`` and PostgreSQL 10.6
    # There are some warnings (in red) that show up during the build. You can hide
    # them by prefixing each apt-get statement with DEBIAN_FRONTEND=noninteractive

    RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common postgresql-10 postgresql-client-10 postgresql-contrib-10
    # 这里要注意文件路径的rwx权限问题.
    USER root
    RUN mkdir -p ${PG_DATADIR} && chown -R postgres:postgres ${PG_DATADIR}
    RUN mkdir -p ${PG_LOGDIR} && chown -R postgres:postgres ${PG_LOGDIR}

    # Adjust PostgreSQL configuration so that remote connections to the
    # database are possible.
    USER postgres
    RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/10/main/pg_hba.conf

    # And add ``listen_addresses`` to ``/etc/postgresql/10.6/main/postgresql.conf``
    RUN echo "listen_addresses='*'" >> /etc/postgresql/10/main/postgresql.conf

    # Create a PostgreSQL role named ``docker`` with ``docker`` as the password and
    # then create a database `docker` owned by the ``docker`` role.
    # Note: here we use ``&&\`` to run commands one after the other - the ``\``
    # allows the RUN command to span multiple lines.
    RUN /etc/init.d/postgresql start && psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" && createdb -O docker docker

    # Expose the PostgreSQL port
    EXPOSE 5432/tcp
    # Add VOLUMEs to allow backup of config, logs and databases
    VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql/10/main"]
    # RUN ${PG_BINDIR}/initdb -D ${PG_DATADIR}

    # Set the default command to run when starting the container
    # 这里如果是9.6版本那就要写成/usr/lib/postgresql/9.6/bin/postgres.好像10.6就直接如下面写就可以了.
    CMD ["/usr/lib/postgresql/10/bin/postgres", "-D", "/var/lib/postgresql/10/main", "-c", "config_file=/etc/postgresql/10/main/postgresql.conf"]
  • pgsql.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

- name: 创建WORKDIR
file:
path: workdir
state: directory
recurse: yes

- name: 上传Dockerfile到目标机的/tmp
# https://docs.ansible.com/ansible/latest/modules/synchronize_module.html?highlight=synchronize
synchronize:
src: pgsql/file/Dockerfile
dest: workdir

- name: 编译PostgreSQL Server镜像
# 参考地址 https://docs.ansible.com/ansible/latest/modules/docker_image_module.html?highlight=docker_image
# https://www.postgresql.org/download/linux/debian/
docker_image:
name: postgresql-10
tag: v6
path: workdir
# dockerfile: file/Dockerfile
state: present

- name: 创建VOLUME的目录
# https://docs.ansible.com/ansible/latest/modules/file_module.html
become: yes
file:
path: ./pgsql-vol/10/main
state: directory
# 这里这了避免使用root运行docker,同时也避免使用root运行postgresql,把这个卷目录所有者改成docker里的postgres的uid:gid的值,才能满足前述使用.这里为uid=111(postgres) gid=121(postgres) groups=121(postgres),120(ssl-cert)
owner: postgres
group: postgres
recurse: yes

# # https://docs.ansible.com/ansible/latest/modules/docker_volume_module.html?highlight=docker_volume
# - name: 创建数据容器卷
# docker_volume:
# name: pgdb_001
# driver_options:
# device: ./docker/volume/pgsql-vol

- name: 创建 postgresql 容器
# 参考地址 https://docs.ansible.com/ansible/latest/modules/docker_container_module.html?highlight=docker
# 这里可以等同于command模块的命令: ``command: docker run -p 5432:5432 -d --name pgsql7 --user postgres -v ~/pgsql-vol:/var/lib/postgresql postgresql-10:v6``
docker_container:
name: pgsql
image: 'postgresql-10:v6'
# docker 网络部分 https://docs.ansible.com/ansible/latest/modules/docker_network_module.html
# network_mode: host
dns_servers:
- '8.8.8.8'
- '100.100.2.136'
published_ports:
- '5432:5432'
state: started
# restart_policy: always
# detach: no
user: postgres
# https://www.katacoda.com/courses/docker/persisting-data-using-volumes
volumes:
- ./pgsql-vol:/var/lib/postgresql

Jenkins安装

谢谢支持

  • 微信二维码: