1. 规划节点
IP | 主机名 | 节点 |
---|---|---|
192.168.200.10 | master | docker-compose |
2. 基础准备
登录OpenStack平台,使用提供的CentOS_7.5_x86_64_XD.qcow2镜像创建云主机,软件包docker- compose.tar.gz上传到/root目录下
3. 基础环境准备
3.1配置yum源
上传文件&解压文件&配置yum源
# 解压文件到/opt/
master # tar -zxvf docker-compose.tar.gz -C /opt/
# 备份原来的yum文件
master # gzip /etc/yum.repos.d/*
# 配置yum文件
master # vi /etc/yum.repos.d/docker.repo
[docker]
name=docker
baseurl=file:///opt/docker-compose
gpgcheck=0
enabled=1
3.2 配置主机映射
配置主机映射
master # vi /etc/hosts ...... 192.168.200.10 master
3.3 配置防火墙以及SElinux
配置防火墙以及SElinux
# 清除所有定制的规则
master # iptables -F
# 清除所有用户“自定义”的chain
master # iptables -X
# 将所有的chain的计数与流量统计都归零
master # iptables -Z
master # iptabes-save
master # sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
master # reboot
3.4 关闭swap分区
Swap分区通常被称为交换分区,当实际内存不够用的时候,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。但是频繁的读写硬盘,会显著降低操作系统的运行速率。
永久禁用虚拟内存:
master # swapoff -a
master # sed -i 's/.*swap.*/#&/' /etc/fstab
3.5 配置路由转发
RHEL/CentOS7上的一些用户报告了由于iptables被绕过而导致流量路由不正确的问题,所以需要在各节点开启路由转发,确保iptables工具可以处理网桥流量。
开启路由转发功能:
master # cat << EOF | tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
3.6 安装docker
安装相关工具:
master # yum -y install -y yum-utils device-mapper-persistent-data lvm2
安装Docker:
master # yum install -y docker-ce
master # systemctl start docker.service && systemctl enable docker.service
Docker从v1.6.15开始到v2.x.x,Docker系统相关的所有镜像都托管在Dockerhub仓库。Dockerhub节点在国外,国内直接拉取镜像会有些缓慢。为了加速镜像的下载,可以通过参数“registry-mirrors”给Docker配置国内的镜像地址。
Docker默认只信任TLS加密的仓库地址(https),所有非https仓库默认无法登录和拉取镜像。“insecure-registries”参数字面意思为不安全的仓库,通过添加这个参数对非https仓库进行授信。可以设置多个insecure-registries地址,以数组形式书写,地址不能添加协议头(http)。
OverlayFS是一个新一代的联合文件系统,类似于AUFS,但速度更快,实现更简单。Docker为OverlayFS提供了两个存储驱动程序:旧版的overlay和新版的overlay2(更稳定),通过“storage-driver”参数配置其文件系统。
容器在运行时会产生大量日志文件,很容易占满磁盘空间,可通过“log-opts”字段配置日志驱动来限制文件大小与文件的数量。
daemon.json文件配置如下:
master # cat > /etc/daemon.json << EOF { "insecure-registries":["0.0.0.0/0"], "registry-mirros":["https://7bezldxe.mirror.aliyuncs.com/"], "exec-opts":["native.cgroupdriver=cgroupfs"] } EOF
重启Docker:
master # systemctl restart docker.service
导入镜像:
master # docker load -i /opt/offline_images.tar
4. 部署DockerCompoes
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。Compose允许用户通过一个单独的docker-compose.yaml模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project)。Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。
Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。
使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
4.1安装Docker-Compose
安装DockerCompose:
master # cd /opt/
master # chmod +x v1.25.5-docker-compose-Linux-x86_64
master # mv v1.25.5-docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
查看版本信息
master # docker-compose version
二、Docker-Compose编排部署服务
1. 规划节点
IP | 主机名 | 节点 |
---|---|---|
192.168.200.10 | master | docker-compose |
2. 基础准备
Docker-ce和DockerCompose已经安装完成
3. YAML知识补充
YAML是“YAML Ain't a Markup Langua”(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。
YAML的配置文件后缀为.yml或.yaml,如test.yml。
YAML的基本语法规则:
-
大小写敏感
-
使用缩进表示层级关系
-
缩进时不允许使用tab建,只允许使用空格
-
缩进的空格数目不重要,只要相同层级的元素左侧对其即可。
YAML支持的数据结构如下
-
对象:键值对的集合,又称为映射(mapping)/哈希(hashes)/字典(dictionary)
-
数组:一组按次序排列的值,又称为序列(sequence)/列表(list)
-
纯量(scalars):单个的、不可再分的值
3.1YAML对象
对象键值对使用冒号结构表示key:value,冒号后面要加一个空格。
也可以使用key{key1:value1,key2:value2,key3:value3...}。
还可以使用缩进表示层级关系
key child-key value child-key value2
较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的key,配合一个冒号加一个空格代表value
?
complexkey1 complexkey2 : complexvalue1 complexvalue2意思即对象的属性是一个数组[complexkey1,complexkey2],对应的值也是一个数组[complexvalue1,complexvalue2]。
3.2YAML数组
以 - 开头的行表示构成一个数组:
- A - B - C
YAML支持多维数组,可以使用行内表示:
key value1 value2 ...
数据结构的子成员是一个数组,则可以在该项下面缩进一个空格。
A B B一个相对复杂的例子:
companies id1 name company1 price 200W id2 name company2 price 500W
意思就是companies属性是一个数组,每一个数组元素又是由id、mane、price三个属性构成
数组也可以使用流式(flow)的方式表示:
companies id1 name company1 price 200W id2 name company2 price 500W
3.3复合结构
数组和对象可以构成复合结构,例:
languages Ruby Perl Python websites YAML yaml.org Ruby ruby-lang.org Python python.org Perl use.perl.org
转换为json为:
{ languages: ['Ruby'.'Perl','Python'], websites: { YAML: 'yaml.org', Ruby: 'ruby-lang.org', Python: 'python.org', Perl: 'use.perl.org' } }
3.4纯量
纯量是最基本的,不可再分的值,包括:
-
字符串
-
布尔值
-
整数
-
浮点数
-
Null
-
时间
-
日期
使用一个例子来快速了解纯量的基本使用:
boolean TRUE # true,Trur都可以 FALSE # false,False都可以 float 3.14 6.8523015e+5 # 可以使用科学计数法 int 123 0b1010_0111_0100_1010_1110 # 二进制表示 null nodeName'node' parent ~ # 使用~表示null string 哈哈 'Hello world' # 可以使用双引号或单引号表过特殊字符 newline newline2 # 字符串可以拆成多行,每一行会被转化成一个空格 date 2021-09-17 # 日期必须使用ISO 8601格式,即yyyy-MM-dd datetime 2021-09-17T08:00:00+08:00 # 时间使用ISO 8601格式,时间和日期之间使用T链接,最后使用+代表时区
3.5引用
“&”和“*”可以用来引用:
defaults&defaults adapter postgres host localhost development database myapp_development <<*defaults test database myapp_test <<*defaults
相当于:
defaults&defaults adapter postgres host localhost development database myapp_development adapter postgres host localhost test database myapp_test adapter postgres host localhost
&用来建立锚点(dafaules),<< 表示合并到当前数据,*用来引用锚点。
下面是另一个例子:
&showell Steve Clark Brian Oren *showell4. Dockerfile知识补充
Dockerfile是一个包含用于组合镜像的命令的文本文档。可以使用在命令行中调用任何命令。Docker通过读取Dockerfile中的指令自动生成镜像。
Dockerfile一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,“#”为Dockerfile中的注释。
Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本镜像,第一条指令必须是FROM。一个声明以“#”字符开头则被视为注释。可以在Docker文件中使用RUN、CMD、FROM、EXPOSE、ENV等指令。
4.1基础指令
FROM用于指定基础镜像,必须为第一个命令。格式如下:
FROM <image> FROM <image>:<tag> FROM <image>@<digest>
示例:
FROM mysql:5.6
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
MAINTAINER用于指定维护者信息,格式如下:
MAINTAINER <name>
示例:
MAINTAINER Double MAINTAINER Double@163.com MAINTAINER Double <Double@163.com>
RUN用于构建镜像时执行的命令。
RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行方式的格式:
RUN <command>
exec执行方式的格式如下:
RUN ["executable","param1","param2"]
示例:
RUN ["executable","param1","param2"] RUN apk update RUN ["/ect/execfile","arg1","arg2"]
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache。
ADD用于将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被加压),可以访问网络资源,类似wget。格式如下:
ADD <src>...<dest> ADD ["<src>",..."<dest>"] # 用于支持包含空格的路径
示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件 ADD hom?.txt /mydir/ # ?替代一个单字符,例如:"home.txt" ADD test relativeDir/ # 添加"test"到`WORKDIR`/relativeDir/ ADD test /absoluteDir/ # 添加"test"到/absoluteDir/
COPY的功能类似ADD,但是不会自动解压文件,也不能访问网络资源。
CMD用于构建容器后调用,也就是在容器启动时才进行调用,格式如下:
CMD ["executable","param1","param2"](执行可执行文件,优先) CMD ["param1","param2"](设置了ENTRYPOINT,则直接调用ENTROPOINT添加参数) CMD command param1 param2 (执行shell内部的命令)
示例:
CMD echo "This is a test." wc - CMD ["/usr/bin/wc","--help"]
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
ENTRYPOINT用于配置容器,使其可执行化。配合CMD可省去"application",只使用参数,格式如下:
ENTRYPOINT ["executable","param1","param2"](可执行文件,优先) ENTRYPOINT command param1 param2 (shell内部命令)
示例:
FROM ubuntu ENTRYPOINT ["top","-b"] CMD ["-c"]
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当作参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
LABEL用于为镜像添加元数据。格式如下:
LABEL <key>=<value><key>=<value><key>=<value>...
示例:
LABEL version="1.0" description="这是一个Web服务器" by="IT笔录"
使用LABEL指定元数据时,一条LABEL可以指定一条或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过LABEL指令指定,以免生成过多的中间镜像。
ENV用于设置环境变量。格式如下:
ENV <key> <value> # <key> 之后所有的内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量。 ENV <key>=<value> ... # 可以设置多个变量,每个遍历为一个<key>=<value>的键值对,如果<key>中包含空格,可以使用\来转义,也可以通过""进行标识;另外,反斜线也可以用于续行
示例:
ENV myName Join Doe ENV myDog Rex The Dog ENV myCat=fluffy
EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口。
VOLUME用于指定 持久化目录。格式如下:
VOLUME ["/path/to/dir"]
示例:
VOLUME ["/data"] VOLUME ["/var/www","/var/log/apache2","/etc/apache2"]
一个卷可以存在与一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
-
卷可以容器之间共享和重用
-
容器并不一定要和其他容器共享卷
-
修改卷后会立即生效
-
对卷的操作不会对镜像产生影响
-
卷会一直存在,直到没有任何容器使用它
WORKDIR用于指定工作目录,类似cd命令。格式如下:
WORKDIR /path/to/workdir
示例:
WORKDIR /a (这时工作路径为/a) WORKDIR b (这时工作目录为/a/b) WORKDIR c (这时工作目录为/a/b/c)
通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录
USER用于指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户。格式如下:
USER user USER user:group USER uid USER uid:gid USER user:gid USER uid:group
示例:
USER www
使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。
ARG用于指定传递给构建运行时的变量。格式如下:
ARG <name>[=<default value>]
示例:
ARG site ARG build_user=www
NBUILD用于设置镜像触发器。格式如下:
ONBUILD [INSTRUCTION]
示例:
ONBUILD ADD ./app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
当所构建的镜像被利用作其他镜像的基础镜像,该镜像中的触发器会被触发。
4.2Dockerfile案例
首先准备一个linux的基础镜像:
master # docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos centos7.5.1804 cf49811e3cdb 19 months ago 200MB
在一个空白目录中,准备好相应的软件包,并建立一个文本文件,并命名为Dockerfile:
master # mkdir mydocker master # cd mydocker master # cp -rvf /opt/jdk-8u141-linux-x64.tar.gz .
构建一个Dockerfile 内容如下:
master # vi Dockerfile # build a new image with basic centos FROM centos:centos7.5.1804 # who is the author MAINTAINER Double # make a new directory to store the jdk files RUN mkdir /usr/local/java # copy the jdk archive to the image,and it will automaticlly unzip the tar file ADD jdk-8u141-linux-x64.tar.gz /usr/local/java/ # make a symbol link RUN ln -s /usr/local/java/jdk1.8.0_141 /usr/local/java/jdk # set environment variable ENV JAVA_HOME /usr/local/java/jdk ENV JRE_HOME ${JAVA_HOME}/jre ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib ENV PATH ${JAVA_HOME}/bin:$PATH
根据Dockerfile创建新镜像:
master # docker build -t="centos-jdk" . ...... Successfully built cd9b1e5aaae3 Successfully tagged centos-jdk:latest
查看新建立的镜像:
master # docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos-jdk latest cd9b1e5aaae3 46 minutes ago 576MB centos centos7.5.1804 f49811e3cdb 19 months ago 200MB
建立容器,查看新的镜像中的JDK是否正确:
master # docker run -it centos-jdk /bin/bash 8aabd21e9def # java -version java version "1.8.0_141" Java(TM) SE Runtime Environment (build 1.8.0_141-b15) Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode) 8aabd21e9def # echo $JAVA_HOME /usr/local/java/jdk 8aabd21e9def # exit
4.3Compose的基本使用
(1)准备
创建一个测试目录:
master # mkdir composetest master # cd composetest
在测试目录中创建一个名为app.py的文件,内容如下:
matest # vi app.py import time import redis from flask import Flask app=Flask(__name__) cache=redis.Redis(host='redis',port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count)
在此示例中,redis是应用程序网络上的redis容器的主机名,该主机使用的端口为6379.
在composetest目录中创建另一个名为requirements.txt的文件,内容如下:
master # vi requirements.txt flask redis
(2)创建Dockerfile文件
在composetest目录中,创建一个名为Dockerfile的文件,内容如下:
matest # vi Dockerfile FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["flask","run"]
Dockerfile内容解释:
-
FROM python:3.7-alpine:从Python3.7镜像开始构建镜像。
-
WORKDIR /code:将工作目录设置为/code。
-
RUN apk add --no-cache gcc musl-dev linux-headers:安装gcc
-
COPY requirements.txt requirements.txt:复制requirements.txt.
-
RUN pip install -r requirements.txt:安装Python依赖项。
-
COPY . .:将 . 项目中的当前目录复制到 . 镜像中的工作目录。
-
CMD ["flask","run"]:容器提供默认执行的命令为:flask run。
(3)创建docker-compose.yml
在测试目录中创建一个名为docker-compose.yml的文件,内容如下:
master # vi docker-compose.yml version'3' services web build. ports "5000:5000" redis image"redis:alpine"
该Compose文件定义了两个服务:web和redis。
-
web:该web服务使用从Dockerfile当前目录中构建的镜像。然后,他将容器和主机绑定到暴露的端口5000。
-
redis:该redis服务使用redis镜像。
(4)使用Compose命令构建和运行应用
在测试目录中,执行以下命令来启动应用程序:
master # docker-compose up
如果你想在后台执行该服务可以加上-d参数:
master # docker-compose up -d
4.4compose实战
(1)使用Docker Compose部署WordPress
创建docker-comopse.yml:
master # mkdir wordpress
master # cd wordpress/
master # vi docker-compose.yml
version'3.3' services db image mysql5.7
volumes db_data:/var/lib/mysql
restart always
environment
MYSQL_ROOT_PASSWORD somewordpress
MYSQL_DATABASE wordpress
MYSQL_USER wordpress
MYSQL_PASSWORD wordpress
wordpress depends_on
db
image wordpress latest
ports "8000:80"
restart always environment
WORDPRESS_DB_HOST db3306
WORDPRESS_DB_USER wordpress
WORDPRESS_DB_PASSWORD wordpress
WORDPRESS_DB_NAME wordpress volumes db_data
使用Compose编排部署WordPress
master # docker-compose up -d
Creating network "wordpress_default" with the default driver
Creating volume "wordpress_db_data" with default driver
Creating wordpress_db_1 ... done
Creating wordpress_wordpress_1 ... done
master # docker-compose ps
[root@docker-compose wordpress]# docker-compose ps Name Command State Ports
-------------------------------------------------------------------------------------
wordpress_db_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
wordpress_wordpress_1 docker-entrypoint.sh apach ... Up 0.0.0.0:8000->80/tcp
-
在浏览器端通过http://IP:8000访问WordPress
-
配置用户信息,点击“Install WordPress”
-
登录WordPress
-
至此,使用Compose编排部署WordPress就完成了。
(2)使用Docker Compose部署Owncloud
编写docker-compose.yml
master # mkdir owncloud
master # cd owncloud
master # vi docker-compose.yml
version'3'
services
owncloud
image owncloud
links mysql:mysql
volumes "/data/db/owncloud:/var/www/html/data"
ports 5679:80
mysql
image mysql5.7
volumes
"/data/mysql/:/var/lib/mysql"
ports
3306:3306
environment
MYSQL_ROOT_PASSWORD"123456"
MYSQL_DATABASE ownCloud
使用Compose编排部署owncloud:
master # docker-compose up -d
Creating network "ownclowd_default" with the default driver
Creating ownclowd_mysql_1 ... done
Creating ownclowd_owncloud_1 ... done
master # docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------
ownclowd_mysql_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
ownclowd_owncloud_1 docker-entrypoint.sh apach ... Up 0.0.0.0:5679->80/tcp
-
在浏览器端通过http://IP:5679访问owncloud
-
创建管理员账号并登录
-
至此,使用Compose编排部署ownCloud就完成了