CI/CD之Docker容器DevOps知識匯總

容器與虛擬主機的區(qū)別

安裝

Mac

下載并安裝即可:https://download.docker.com/mac/stable/Docker.dmg

# 查看信息的一些命令
docker --version
docker version
docker info
# 還可安裝Kitematic進行可視化的安裝

Mac/Windows下安裝虛機的小技巧:Vagrant-首先要安裝VirtualBox灌诅,然后在Vagrant下載頁面進行軟件的下載

vagrant --help
vagrant version

# 快速創(chuàng)建虛擬機
mkdir -p vagrant/centos
cd vagrant/centos/
# 初始化Vagrantfile
vagrant init centos/7
# 安裝
vagrant up
# 通過ssh進入
vagrant ssh
# 查看狀態(tài)
vagrant status
# 停止服務(wù)
vagrant halt
# 刪除
vagrant destroy

# 因網(wǎng)絡(luò)問題猜拾,有時需要通過迅雷等軟件先把文件下載下來挎袜,再進行本地安裝
# 本地安裝box,以Windows 10為例
vagrant box add Microsoft/EdgeOnWindows10 /path/to/virtualbox.box 
vagrant init Microsoft/EdgeOnWindows10
vagrant up

# 安裝 scp 插件全景,然后可通過 vagrant scp 命令拷貝本地文件或目錄到主機上
vagrant plugin install vagrant-scp

搜索相關(guān)操作系統(tǒng)的Vagrantfile:https://app.vagrantup.com/boxes/search爸黄,找到相應(yīng)文件后創(chuàng)建一個名為Vagrantfile的文件或直接根據(jù)命令初始化馆纳,再使用vagrant up進行安裝

以CentOS安裝為例:

# 卸載舊版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest \
docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
# 安裝requirements
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加repo
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安裝docker
sudo yum install docker-ce -y
# 啟動docker
sudo systemctl start docker
sudo systemctl enable docker
# 運行Hello World
sudo docker run hello-world

啟動 Vagrant 自動安裝 Docker鉴裹,修改 Vagrantfile 末尾為

config.vm.provision "shell", inline: <<-SHELL
    sudo yum remove docker docker-common docker-selinux docker-engine
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sudo yum install -y docker-ce
    sudo systemctl start docker
  SHELL
end

# 其它
# 設(shè)置橋接網(wǎng)絡(luò)
config.vm.network "public_network", :bridge => 'en0: Wi-Fi (AirPort)'
#設(shè)置私有 IP
config.vm.network "public_network", ip: "192.168.1.120"

Docker Machine

Windows 和 Mac 安裝時會默認帶有 Docker Machine, Linux 下安裝參見:https://github.com/docker/machine/releases/

# 創(chuàng)建一個名為 demo 的虛機
docker-machine create demo
# 顯示虛擬機列表
docker-machine ls
# SSH 連接 demo
docker-machine ssh demo
# 啟動 demo
docker-machine start demo
# 關(guān)閉 demo
docker-machine stop demo
# 刪除 demo
docker-machine rm demo
# 本地執(zhí)行
docker-machine env demo
eval $(docker-machine env demo)
# unset
docker-machine env --unset
eval $(docker-machine env --unset)

# 通過添加 vagrant 用戶到 docker 組督禽,在執(zhí)行 docker 命令時不再 需要添加 sudo
sudo gpasswd -a vagrant docker

https://github.com/AliyunContainerService/docker-machine-driver-aliyunecs
把文件重命名為:/usr/bin/docker-machine-driver-aliyunecs
# 驗證安裝是否成功
docker-machine create -d aliyunecs --help
# 使用 Docker Machine 在阿里云上創(chuàng)建 Host
docker-machine create -d aliyunecs --aliyunecs-io-optimized=optimized --aliyunecs-instance-type=ecs.c4.large --aliyunecs-access-key-id=xxx --aliyunecs-access-key-secret=xxx --aliyunecs-region=cn-hangzhou demo

此外還可通過 Docker Playground 來進行測試,但經(jīng)測試國內(nèi)速度較慢且經(jīng)常會空間不足無法創(chuàng)建胧谈,以上方法中推薦 Vagrant菱肖,靈活性較 Docker Machine 更強稳强。

Docker 命令

# Dockerfile
from hub.c.163.com/library/tomcat
MAINTAINER Alan alan@xxx.com
COPY demo.war /usr/local/tomcat/webapps
# Build渠缕,demo:latest 分別為名稱和標簽
docker build -t  demo:latest .
# 指定端口并運行 -d 后臺運行 -p 指定端口
docker run -d -p 8888:8080  demo
# 交互式運行 Container
docker run -it centos
# 以 /bin/bash 進入鏡像交互式環(huán)境
docker run -it <IMAGE ID> /bin/bash

docker pull hub.c.163.com/library/tomcat:latest
# 查看容器名等信息
docker ps
# 進入容器
docker exec -it 12e1b6c023e bash
# 拷貝到本地
docker cp <container id>:/demo.war ./
docker inspect <container id>

# 安裝 Wordpress(docker-compose.yml)
docker-compose build
docker-compose up

# 停止當前所有運行的 Docker
docker stop $(docker ps -a -q)
# 查看鏡像
docker images
docker image ls
# 刪除鏡像,-f 為強制刪除
docker rmi -f <image id>
#查看容器
docker container ls # 運行中的容器
docker container ls -a # 列出所有容器亦鳞,與 docker ps -a相同
# 刪除容器
docker container rm <container id>
# 列出所有容器 id,與docker container ls -a | awk {'print $1'}相似
docker container ls -aq 
# 刪除所有容器
docker rm $(docker container ls -aq) # 或docker rm $(docker ps -aq)
# 刪除已退出容器
docker rm $(docker container ls -f "status=exited" -q)
#容器運行日志
docker logs <CONTAINER ID>

Docker的鏡像和容器

Docker Engine

  • 后臺進程(dockerd)
  • REST API Server
  • CLI接口(docker)
Docker Engine

底層技術(shù)支持

  • Namespaces:做隔離 pid, net, ipc, mnt, uts
  • Control groups:做資源限制
  • Union file systems:Container 和 image 的分層
Docker Architecture

Docker 鏡像

# 1俊抵、手寫 Dockerfile 自行 build
FROM ubuntu:14.04
LABEL maintainer="Alan Hou <xxx@gmail.com>"
RUN apt-get update && apt-get install -y redis-server
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server"]
# build
docker build -t  ubuntu-14:latest .

# 2徽诲、docker pull
sudo docker pull ubuntu:14.04

# sudo docker images 進行查看

什么是 Image?

  • 文件和 meta data 的集合(root filesystem)
  • 分層的谎替,并且每一層都可以添加改變刪除文件钱贯,成為一個新的 image
  • 不同的 image 可以共享相同的 layer
  • Image 本身是 read-only 的
Docker 鏡像
# 執(zhí)行 hello-world
docker pull hello-world
docker run hello-world

# 手寫 base image hello-world
mkdir hello-world
cd hello-world/
vi hello.c
#include<stdio.h>
int main()
{
        printf("hello docker!\n");
}

sudo yum install gcc glibc glibc-static -y
gcc -static hello.c -o hello
# 創(chuàng)建 Dockerfile
vi Dockerfile
FROM scratch
ADD hello /
CMD ["/hello"]

# build 我們的 base image
docker build -t alanhou/hello-world .
# 此時執(zhí)行docker image ls就可以看到alanhou/hello-world
# 運行
docker run alanhou/hello-world

什么是 Container?

  • 通過 Image 創(chuàng)建(copy)
  • 在 Image layer 之上建立一個 container layer(可讀寫)
  • 類比面向?qū)ο螅侯?Image)和實例(Container)
  • Image負責 app 的存儲和分發(fā),Container 負責運行 app
# container commit 為 image
docker container commit/docker commit

# 示例:(把拉下來的 CentOS  進行修改后生成 Image袄友,不推薦)
docker commit musing_aryabhata alanhou/centos-alan

docker image build/docker build

# 示例
vi Dockerfile
FROM centos
RUN yum install -y vim

docker build -t alanhou/centos-vim .

Dockerfile

FROM 指定 base image
FROM scratch # 從0開始
# 選擇其它 base image
FROM centos  
FROM ubuntu:14.04

LABEL 指定 Metadata
LABEL maintainer="xxx@gmail.com"
LABEL version="1.0"
LABEL description="Demo description"

RUN執(zhí)行命令
RUN yum update && yum install -y vim python-dev
RUN apt-get update && apt-get install -y perl \
pwgen --no-install-recommends && rm -rf \
/var/lib/apt/lists/*
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'

WORKDIR 設(shè)定當前工作目錄
WORKDIR /test # 如果沒有會自動創(chuàng)建
WORKDIR demo
RUN pwd

ADD and COPY把本地文件添加到 image 中
ADD hello /
ADD test.tar.gz / # 添加到根目錄并解壓
WORKDIR /root
ADD hello test/ # /root/test/hello
WORKDIR /root
COPY hello test/

ENV
ENV MYSQL_VERSION 5.6 # 設(shè)置常量
RUN apt-get install -y mysql-server= "${MYSQL_VERSION}" \ #引用常量
&& rm -rf /var/lib/apt/lists/*

VOLUMN and EXPOSE 存儲和網(wǎng)絡(luò)
CMD and ENTRYPOINT
# RUN:執(zhí)行命令并創(chuàng)建新的 Image Layer
# CMD:設(shè)置容器啟動后默認執(zhí)行的命令和參數(shù);如果 docker run 指定了其它命令鸠按,CMD命令被忽略待诅;如果定義了多個 CMD募书,只有最后一個會執(zhí)行
# ENTRYPOINT:設(shè)置容器啟動時運行的命令莹捡;不會被忽略篮赢,一定會執(zhí)行启泣;最佳實踐:寫一個 shell 腳本作為 entrypoint

# Shell 格式
RUN apt-get install -y vim
CMD echo "hello docker"
ENTRYPOINT echo "hello docker"

# Exec 格式
RUN ["apt-get", "install", "-y", "vim"]
CMD ["/bin/echo", "hello docker"]
ENTRYPOINT ["/bin/echo", "hello docker"]

Docker 官方 Image 文件:https://github.com/docker-library
Docker 官方文檔:https://docs.docker.com/engine/reference/builder/

Docker鏡像的發(fā)布

https://hub.docker.com

首先注冊用戶

方法一:進入服務(wù)器執(zhí)行

docker login
docker image push/docker push <REPOSITORY> # 如extratime/hello-world

方法二(推薦)Create Automated Build,關(guān)聯(lián) GitHub纱耻,會自動根據(jù) Dockerfile 自動生成鏡像

通過registry 搭建自己的私有 Docker Registry

sudo docker run -d -p 5000:5000 --restart always --name registry registry:2

默認 push 私有服務(wù)器不被信任(Get https://192.168.1.6:5000/v2/: http: server gave HTTP response to HTTPS client)

docker build -t xxx.xxx.xxx.xxx:5000/hello-world .

vi /etc/docker/daemon.json
{"insecure-registries":["xxx.xxx.xxx.xxx:5000"]}

vi /lib/systemd/system/docker.service
EnvironmentFile = /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl reload docker

docker push xxx.xxx.xxx.xxx:5000/hello-world

Docker Registry Api 可用于查看驗證 push 是否成功,如通過 http://your.ip.address:5000/v2/_catalog查看倉庫蘑志,得到如下結(jié)果:

{
    repositories: [
        "hello-world"
    ]
}

示例文件(制作基于 Flask Hello World 程序的鏡像)

# Dockerfile
FROM python:2.7
LABEL maintainer="Alan Hou<xxx@gmail.com>"
RUN pip install flask
COPY app.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["python", "app.py"]

docker build -t alanhou/flask-hello-world .
# 對于中間狀態(tài)的鏡像可以通過/bin/bash 查看環(huán)境中存在的問題
docker run -it bacce0142ae /bin/bash
# 運行
docker run -d alanhou/flask-hello-world
# 進入運行中的容器
docker exec -it <CONTAINER ID> /bin/bash

示例文件2(帶參數(shù)執(zhí)行的 Docker Image)

# Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y stress
ENTRYPOINT ["/usr/bin/stress"]
CMD []

# 創(chuàng)建鏡像
docker build -t alanhou/ubuntu-stress .
# 運行
docker run -it alanhou/ubuntu-stress --vm 1

Docker的網(wǎng)絡(luò)

網(wǎng)絡(luò)是基于數(shù)據(jù)包的通信方式,網(wǎng)絡(luò)的分層

網(wǎng)絡(luò)的分層

Ping(ICMP協(xié)議)用于驗證 IP 的可達性(防火墻可能會禁止 Ping 操作)旱幼;telnet 用于檢查服務(wù)的可用性(telnet ip.addr port)

Network Namespace 的小測試

# 添加網(wǎng)絡(luò)命名空間
sudo ip netns add test1
sudo ip netns add test2
# 查看
sudo ip netns list
# 設(shè)置關(guān)聯(lián)
sudo ip link add veth-test1 type veth peer name veth-test2
sudo ip link set veth-test1 netns test1
sudo ip link set veth-test2 netns test2
# 設(shè)置 IP
sudo ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
sudo ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
# 啟動
sudo ip netns exec test1 ip link set dev veth-test1 up
sudo ip netns exec test2 ip link set dev veth-test2 up
# 查看IP 地址
sudo ip netns exec test1 ip a
sudo ip netns exec test2 ip a
# Ping 測試
sudo ip netns exec test2 ping 192.168.1.1

Docker 默認網(wǎng)絡(luò)Bridge

# 啟動容器 test1
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done"
# 查看網(wǎng)絡(luò)并顯示NETWORK ID
docker network ls
docker network inspect <NETWORK ID>
# 安裝并查看橋接網(wǎng)絡(luò)
sudo yum install -y bridge-utils
brctl show
# 啟動容器 test2
docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done"
docker network inspect bridge

# Docker Link
docker stop test2
docker rm test2
# 重新啟動 test2
docker run -d --name test2 --link test1 busybox /bin/sh -c "while true; do sleep 3600; done"
docker exec -it test2 /bin/sh
# 在交互命令中除 ip 外還可通過 ping test1來測試連接
# 創(chuàng)建網(wǎng)絡(luò)(通過-d 指定 driver)
docker network create -d bridge my-bridge
# 創(chuàng)建容器并指定網(wǎng)絡(luò)
docker run -d --name test3 --network my-bridge busybox /bin/sh -c "while true; do sleep 3600; done"
# 連接已有容器到指定網(wǎng)絡(luò)
docker network connect my-bridge test2
# 注:連接到自定網(wǎng)絡(luò)中的容器默認相互 link冬三,所以在 test2中通過 ping test3是可以連接的

# 端口映射 -p  為Port Map
docker run --name web -d -p 80:80 nginx

容器網(wǎng)絡(luò) none & host

docker run -d --name test1 --network none busybox /bin/sh -c "while true; do sleep 3600; done"
# 查看 none網(wǎng)絡(luò)
docker network inspect none
# 進入容器勾笆,通過 ip a 命令會發(fā)現(xiàn)僅存在本地回環(huán)地址 lo窝爪,即局域網(wǎng)內(nèi)無法訪問
docker exec -it test1 /bin/sh
# 刪除
docker stop test1 && docker rm test1

# 創(chuàng)建并設(shè)置 test1網(wǎng)絡(luò)為 host
docker run -d --name test1 --network host busybox /bin/sh -c "while true; do sleep 3600; done"
# 查看 host網(wǎng)絡(luò)
docker network inspect host
# 進入容器纷跛,通過 ip a可發(fā)現(xiàn)與宿主機相同贫奠,所以若啟動多個服務(wù)(如 Nginx)可能會出現(xiàn)端口沖突的問題
docker exec -it test /bin/sh

更復雜的 Docker 測試

sudo docker run -d --name redis redis
docker build -t alanhou/flask-redis .
# -e 設(shè)置環(huán)境變量
docker run -d -p 5000:5000 --link redis --name flask-redis -e REDIS_HOST=redis alanhou/flask-redis

# app.py
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

# Dockerfile
FROM python:2.7
LABEL maintaner="Alan Hou xxx@gmail.com"
COPY . /app/
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]

Overlay 網(wǎng)絡(luò)和多機容器間通信

# 在兩臺宿主機上分別執(zhí)行
# 配置 etcd(分布式的 key,value 工具,用于管理并防止 IP 沖突)
wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
cd etcd-v3.0.12-linux-amd64
# your.ip.addr為本機 IP谢肾,dest.ip.addr為需連接的服務(wù)器 IP, docker-node1,2可根據(jù)實際情況修改為其它名稱
nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://your.ip.addr:2380 \
--listen-peer-urls http://your.ip.addr:2380 \
--listen-client-urls http://your.ip.addr:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://your.ip.addr:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://your.ip.addr:2380,docker-node2=http://dest.ip.addr:2380 \
--initial-cluster-state new&
# 查看 etcd 服務(wù)狀況
./etcdctl cluster-health
# 重新啟動 docker 服務(wù)
sudo service docker stop
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://your.ip.add:2379 --cluster-advertise=your.ip.addr:2375&

# 創(chuàng)建 overlay 網(wǎng)絡(luò)(另一臺機器會自動創(chuàng)建 docker network ls)
sudo docker network create -d overlay demo

# 在 A 主機上創(chuàng)建
docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done" 
# 在 B 主機上創(chuàng)建
docker run -d --name test2 busybox /bin/sh -c "while true; do sleep 3600; done" 

# 此時會發(fā)現(xiàn)兩個窗口之間可相互 ping 通,即實現(xiàn)了通信弊决,如 docker exec -it test1 ping test2

Docker的持久化存儲和數(shù)據(jù)共享

Docker 持久化數(shù)據(jù)的方案

  • 基于本地文件系統(tǒng)的 Volume:Data Volume飘诗,docker create 或 docker run 時添加-v 參數(shù)
  • 基于 plugin 的 Volume:第三方存儲方案昆稿,如 NAS, AWS

以下為本地文件系統(tǒng)持久化的兩種操作方法:

Data Volume

可通過 Dockerfile中的 VOLUME進行指定,如 MySQL的官方 Dockerfile 中使用VOLUME /var/lib/mysql

sudo docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
sudo docker volume ls
sudo docker volume inspect <VOLUME NAME>
# 可以看到/var/lib/docker/volumes/下有存儲相關(guān)目錄喳瓣,即使刪除容器也不影響畏陕,如需刪除volume惠毁,需手動執(zhí)行
sudo docker volume rm <VOLUME NAME>
# 默認生成的<VOLUME NAME>太長羽莺,可以通過-v 參數(shù)指定盐固,如:
sudo docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
# 會發(fā)現(xiàn)在我們刪除容器后刁卜,重新使用相同的-v 參數(shù)原容器創(chuàng)建的數(shù)據(jù)庫等信息依然存在

Bind Mounting

本地文件和容器之前的一個映射關(guān)系(/home/aaa 為本地,可使用$(pwd)映射本地目錄)

docker run -v /home/aaa:/root/aaa

Docker Compose多容器部署

安裝部署 Wordpress

# 安裝 MySQL容器
docker run -d --name mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql:5.7
# 安裝 Wordpress容器
docker run -d -e WORDPRESS_DB_HOST=mysql:3306 --link mysql -p 80:80 wordpress

Docker Compose是一個可以通過一個 yml 文件定義多容器 Docker應(yīng)用的工具孝情,默認名稱 docker-compose.yml
services:一個 service 代表一個 container,啟動類似 docker run

Windows, Mac 默認已安裝 Docker Compose羔挡,Linux

sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 查看安裝狀況
docker-compose --version

以上述 Wordpress 部署為例

docker-compose.yml

version: '3'

services:

  wordpress:
    image: wordpress
    ports:
      - 80:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-bridge

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-bridge

volumes:
  mysql-data:

networks:
  my-bridge:
    driver: bridge

執(zhí)行

docker-compose up -d
# 或指定 yml 文件
docker-compose -f docker-compose.yml up -d

其它命令

# 停止服務(wù)
docker-compose stop
# 停止并刪除
docker-compose down
# 查看
docker-compose ps
docker-compose images
docker-compose exec ...

水平擴展和負載均衡

# 修改前述docker-compose.yml 文件:刪除 wordpress 下的 ports 部分,并在 services 下添加
lb:
    image: dockercloud/haproxy
    links:
      - wordpress
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
# 執(zhí)行如下命令即可實現(xiàn)負載均衡低矮,數(shù)字3可修改為其它想要啟動的容器數(shù)
docker-compose up --scale wordpress=3 -d

容器編排Docker Swarm

容器編排 Docker Swarm
# 在 Swarm Manager上運行
docker swarm init --advertise-addr=your.ip.add
# 運行結(jié)束時會提示,在 Swarm Work 上運行該命令即可
docker swarm join --token <Swarm Manager Token> your.manager.ip.addr:2377
# 執(zhí)行完成后可在 Swarm Manager 上查看節(jié)點
docker node ls

# 在 Swarm Manager 上創(chuàng)建Service
docker service create --name demo busybox sh -c "while true; do sleep 3600; done"
# 查看 service
docker service ls
# 查看指定 service所在節(jié)點等信息
docker service ps demo
# 水平擴展
docker service scale demo=3
# 刪除
docker service rm demo

基于上述Docker Swarm 集群部署 Wordpress

# 創(chuàng)建 Overlay 網(wǎng)絡(luò)(manager)
docker network create -d overlay demo
# 安裝 MySQL
docker service create --name mysql --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysal-data,destination=/var/lib/mysql mysql:5.7
# 安裝 Wordpress
docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress

此時便完成了 Wordpress 的部署肠虽,我們會發(fā)現(xiàn)通過所有節(jié)點的 IP 均可訪問該站點

集群服務(wù)器間通信 Routing Mesh測試

docker service create --name whoami -p 8000:8000 --network demo -d jwilder/whoami
docker service create --name client -d --network demo busybox sh -c "while true; do sleep 3600; done"

Routing Mesh兩種體現(xiàn)

  • Internal-容器之間的訪問通過 Overlay 網(wǎng)絡(luò)(通過 VIP 虛擬 IP)
  • Ingress-如果服務(wù)有綁定接口闲延,則此服務(wù)可以通過任意 Swarm 節(jié)點的相應(yīng)接口訪問
    • 外部訪問的負載均衡
    • 服務(wù)端口被暴露到各個 Swarm 節(jié)點
    • 內(nèi)部通過 IPVS 進行負載均衡

Ingress 查看相關(guān)命令

sudo yum install -y ipvsadm
sudo nsenter --net=/var/run/docker/netns/ingress_sbox
# 進入 ingress_box 后查看虛擬 IP 指向
sudo iptables -nL -t mangle
# 查看具體 IP
ipvsadm -l
Ingress Network 數(shù)據(jù)走向

Docker Stack部署 Wordpress

docker stack deploy web --compose-file=docker-compose.yml

# docker-compose.yml 修改網(wǎng)絡(luò)為 overlay陆馁,MySQL 僅允許在 Manager 節(jié)點上
version: '3'
services:
  wordpress:
    image: wordpress
    ports:
      - 80:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  mysql-data:

networks:
  my-network:
    driver: overlay

Docker Secret Management

上面的 docker-compose.yml 中包含數(shù)據(jù)庫密碼等敏感信息合愈,類似的信息有:用戶名密碼叮贩、SSH Key、TLS認證和任何不想讓其它人看到的數(shù)據(jù)佛析。對于這類似信息我們需要通過加密的方式進行存儲同時 Service 還可以獲取

# 從文件創(chuàng)建
docker secret create my-pw password.txt
# 命令行創(chuàng)建
echo "xxxxxx" | docker secret create my-pw -
# 查看和刪除 
docker secret ls
docker secret rm
# 以 MySQL為例(--secret 指定前面創(chuàng)建的密鑰益老,默認會在/run/secrets 下創(chuàng)建一個同名的文件并包含對應(yīng)信息)
docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql

# 同樣以 Wordpress 為例,可以前面 Docker Stack 部署的docker-compose.yml文件進行如下修改
environment:
  WORDPRESS_DB_HOST: mysql
  WORDPRESS_DB_PASSWORD: root
# 修改為
secrets:
  - my-pw
environment:
  WORDPRESS_DB_HOST: mysql
  WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw

Service 更新

# 假設(shè)有一個名為 web 的 service寸莫,首先進行橫向擴展,確保更新時服務(wù)不中斷
docker service scale web=2
# image 更新
docker service update --image xxx/xxx web
# 端口更新
docker service update --publish-rm 8080:5000 --publish-add 8888:5000 web

DevOps初體驗—Docker Cloud和Docker企業(yè)版

Docker Cloud

CaaS(Container-as-a-Service)

Docker Cloud:提供容器的管理膘茎、編排桃纯、部署的托管服務(wù)

主要模塊:關(guān)聯(lián)云服務(wù)商、添加節(jié)點行為披坏、創(chuàng)建服務(wù)态坦、創(chuàng)建 Stack、Image 管理

企業(yè)版安裝

Docker Store 中申請30天試用刮萌,

Docker EE安裝方法參見文檔(以 CentOS為例)

安裝 UCP

注:測試安裝時發(fā)現(xiàn)版本僅為17.06.2驮配,當前新版的 UCP 需要18以上的企業(yè)版,因而選擇低版本兼容的 UCP

docker container run --rm -it --name ucp \
  -v /var/run/docker.sock:/var/run/docker.sock \
  docker/ucp:2.2.4 install \
  --host-address <node-ip-address> \
  --interactive

UCP(Universal Control Plane) 相當于一個網(wǎng)頁版的 Swarm着茸,安裝完成后可通過 https://<node-ip-address>:443壮锻,根據(jù)安裝時設(shè)置的用戶名密碼登錄并上傳后臺下載的證書

點擊 Nodes>Add Node,在 worker 節(jié)點服務(wù)器上執(zhí)行生成的docker swarm join 代碼段

Docker UCP

DTR安裝

admin>Admin Settings>Docker Trusted Registry涮阔,選擇 DTR EXTERNAL URL 和UCP NODE猜绣,勾選Disable TLS Verification For UCP,根據(jù)生成的docker run -it --rm docker/dtr install...命令在對應(yīng)的主機上運行

以創(chuàng)建名為 demo 的 Repository 為例:

docker tag image-name:latest dtr.ip.addr/admin/demo
docker login dtr.ip.addr
docker push dtr.ip.addr/admin/demo

此外在 System>Security中 Enable Sanning 用于開啟對鏡像的安全掃描功能敬特,此時即可對倉庫中的鏡像進行安全掃描:

DTS倉庫&掃描

容器編排Kubernetes

Kubternetes架構(gòu)

Minikube

使用 minikube 進行安裝單節(jié)點 K8S集群

brew cask install minikube
# 啟動
minikube start
# 查看設(shè)置及上下文
kubectl config view
kubectl config get-contexts
kubectl cluster-info
# 進入節(jié)點
minikube ssh

K8S最小調(diào)度單位 Pod掰邢,一個 Pod 共享一個 Namespace

# 創(chuàng)建 Pod
kubectl create -f xxx.yml
# 刪除 Pod
kubectl delete -f xxx.yml
# 查看 Pod
kubectl get pods
# 顯示更多信息
kubectl get pods -o wide
# 進入 Pod
kubectl exec -it xxx sh
# 查看 Pod 詳細信息
kubectl describe pods xxx
# 端口轉(zhuǎn)發(fā),以 Nginx pod 為例
kubectl port-forward nginx 8080:80

# ReplicationController
# apiVersion: v1
# kind: ReplicationController
# 查看
kubectl get rc
# 擴展
kubectl scale rc nginx --replicas=2

# ReplicaSet
# apiVersion: apps/v1
# kind: ReplicaSet
# 查看
kubectl get rs
# 擴展
kubectl scale rs nginx --replicas=2 

# Deployment 
# apiVersion: apps/v1
# kind: Deployment
kubectl get deployment
kubectl get deployment -o wide
kubectl get pods
# 設(shè)置鏡像(更新操作)
kubectl set image deployment nginx-deployment nginx=nginx:1.13
# 查看歷史記錄
kubectl rollout history deployment nginx-deployment
# 回復到上一個版本
kubectl rollout undo deployment nginx-deployment
# 創(chuàng)建 service 供外部訪問及查看端口
kubectl expose deployment nginx-deployment --type=NodePort
kubectl get svc

Tectonic

使用Tectonic 搭建多節(jié)點集群

kubectl expose命令會給 Pod 創(chuàng)建 Service 供外部訪問伟阔,Service 主要有三種類型:ClusterIP, NodePort, 外部的LoadBalancer(kubectl expose 通過--type 指定); 也可以使用 DNS辣之,但需要 DNS 的 add-on

容器的的運維和監(jiān)控

docker top
docker state

Weave Scope

sudo curl -L git.io/scope -o /usr/local/bin/scope
sudo chmod a+x /usr/local/bin/scope
scope launch
Weave Scope

heapster

InfluxDB, Grafana

minikube addons list
minikube addons enable heapster
# 重啟
minikube stop
minikube start --extra-config=controller-manager.HorizontalPodAutoscalerUseRESTClients=false
# 自動橫向擴展
# 運行鏡像并暴露端口
kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80
# 創(chuàng)建 HPA( Horizontal Pod Autoscaler),指定最小和最大數(shù)量皱炉,超過50%后就會擴展
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

# 查看
kubectl get deployment php-apache
kubectl get horizontalpodautoscaler
kubectl get svc

# 刪除部署
kubectl delete deployment php-apache
kubectl delete svc php-apache
kubectl delete hpa php-apache

Horizontal Pod Autoscaler Walkthrough

日志采集展示

ELK Stack(ElasticSearch+Logstash+Kibana)

  • Fluentd(log 轉(zhuǎn)發(fā))
  • ElasticSearch(log Index)
  • Kibana(log 可視化)
  • LogTrail(log UI 查看)

本地搭建集群:kubeadm

相應(yīng) yml 文件(替換成對應(yīng)版本):fluentd-elastisearch

集群監(jiān)控方案(Pull 數(shù)據(jù)):https://prometheus.io/

Docker+DevOps實戰(zhàn)—過程和工具

基本流程參見容器的的運維和監(jiān)控部分的圖片

安裝 GitLab怀估,參見Jenkins+Ansible+GitLab自動化部署三劍客

GitLab CI 服務(wù)器搭建

# 安裝 Docker
curl -sSL https://get.docker.com/ | sh
# 安裝 gitlab ci runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
sudo yum install gitlab-ci-multi-runner -y
# 查看是否運行正常
sudo gitlab-ci-multi-runner status
# 設(shè)置 Docker 權(quán)限
sudo usermod -aG docker gitlab-runner
sudo service docker restart
sudo gitlab-ci-multi-runner restart

# 注冊
sudo gitlab-ci-multi-runner register
# 輸入 GitLab 地址和 token(項目頁>Settings>CI/CD>Runners 下的Set up a specific Runner manually
中)
# 設(shè)置完成后在同一版塊的Runners activated for this project中會發(fā)現(xiàn)新增的Runner,激活并在項目下添加.gitlab-ci.yml文件測試,結(jié)果在CI/CD>Pipelines 中查看

Settings>Repository>Protected Branches可設(shè)置禁止 master 分支的 push 行為

Repository>Branches 創(chuàng)建新分支(如 dev)

Settings>General>Merge Request 可進行相關(guān)限制

git fetch
git checkout dev
git push origin dev
# Merge Requests 中進行提交

常見問題

1多搀、Error restarting cluster: restarting kube-proxy: waiting for kube-proxy to be up for configmap update: timed out waiting for the condition

# 刪除重新執(zhí)行
minikube delete
minikube start

原文鏈接:Alan Hou 的個人博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末歧蕉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子康铭,更是在濱河造成了極大的恐慌惯退,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件从藤,死亡現(xiàn)場離奇詭異催跪,居然都是意外死亡,警方通過查閱死者的電腦和手機呛哟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門叠荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扫责,你說我怎么就攤上這事榛鼎。” “怎么了鳖孤?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵者娱,是天一觀的道長。 經(jīng)常有香客問我苏揣,道長黄鳍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任平匈,我火速辦了婚禮框沟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘增炭。我一直安慰自己忍燥,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布隙姿。 她就那樣靜靜地躺著梅垄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪输玷。 梳的紋絲不亂的頭發(fā)上队丝,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音欲鹏,去河邊找鬼机久。 笑死,一個胖子當著我的面吹牛赔嚎,可吹牛的內(nèi)容都是我干的膘盖。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼衔憨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起袄膏,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤践图,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沉馆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體码党,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年斥黑,在試婚紗的時候發(fā)現(xiàn)自己被綠了揖盘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡锌奴,死狀恐怖兽狭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鹿蜀,我是刑警寧澤箕慧,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站茴恰,受9級特大地震影響颠焦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜往枣,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一伐庭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧分冈,春花似錦圾另、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蘑秽,卻和暖如春饺著,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肠牲。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工幼衰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缀雳。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓渡嚣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子识椰,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容