Docker学习笔记

一、简介

Docker是一个开源的应用容器引擎,它是由 Go 语言 开发实现的轻量级容器技术,它是基于 Linux 内核的 cgroupnamespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它隔离的进程,因此也称其为容器。

Docker 架构

二、概念

1. 概要理解

Docker支持安装各种软件并做好配置后编译成镜像,最终可以直接运行镜像产生一个或多个运行于宿主机内核上的容器。为了形象的理解容器,可以简单的理解它为运行在操作系统上的独立沙箱系统,这些沙箱系统内部的文件系统和Linux的非常相似,事实上确是如此,因为Docker就是融合了Linux内核而实现的虚拟化技术,由于具有沙箱的特性,所以各个容器之间是隔离运行的、独立的、互不影响的,程序员甚至不用担心容器内部损坏或者崩溃导致宿主机出错,因为只要删除掉这些有问题的容器,而再运行相关的镜像又会得到全新的容器了,只要不进行数据挂载,整个过程甚至干净不留残余。

2. 核心内容

docker主机(Host):或者称为docker宿主机,即安装了Docker程序的机器。

docker客户端(Client):连接docker主机进行操作的程序。

docker镜像(Images):是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

docker容器(Container):运行镜像后产生的实例称为容器,实质是运行于独立的 命名空间的进程。

docker仓库(Registry):集中存储、分发镜像的仓库服务系统,作用是允许用户上传、下载并管理镜像,包括公有仓库和私有仓库。

20180303165113

3. 对比传统虚拟机

特性虚拟机的架构容器的架构
启动分钟级秒级
性能弱于原生接近原生
硬盘使用一般为GB一般为MB
系统支持量一般几十个单机上千个容器

虚拟机的架构: 每个虚拟机都包括应用程序、必要的二进制文件和库以及一个完整的客户操作系统(Guest OS),尽管它们被分离,它们共享并利用主机的硬件资源,将近需要十几个 GB 的大小。

容器的架构: 容器包括应用程序及其所有的依赖,但与其他容器共享内核。它们以独立的用户空间进程形式运行在宿主机操作系统上。他们也不依赖于任何特定的基础设施,Docker 容器可以运行在任何计算机上,任何基础设施和任何云上。

4. 优势

(1)快速的启动时间

由于Docker容器直接运行于宿主内核,无需启动完整的操作系统即可运行,因此可以做到秒级、甚至毫秒级的启动时间,这大大的节约了开发、测试、部署的时间。

(2)一致的运行环境

开发过程中一个常见的问题是环境一致性问题。由于不同物理机的开发环境不一致,经常出现安装了相同的软件但却有不同的运行效果现象,甚至有的环境下还会出现bug。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,以至于不会再出现 “这段代码在我机器上没问题啊” 这类的问题。

(3)持续交付和部署

Docker可以一次创建或配置镜像,而可以在任意地方正常运行。即"一处构建,到处运行"。

(4)更方便的迁移

Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

(5)更轻量的维护和扩展

Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。

5. 分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

6. 容器存储层

镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层

7. 数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录,当容器内部的目录(文件)映射到宿主机的某目录(文件)时,那么就称这个宿主机的目录(文件)为数据卷。它绕过 UFS,可以提供很多有用的特性,如下:

  • 数据卷 可以在容器之间共享和重用
  • 数据卷 的修改会立马生效
  • 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

三、安装Docker

Docker 分为 CE 和 EE 两大版本。CE 即社区版,EE 即企业版,强调安全,付费使用。

1. 安装旧版本

centos7默认yum源头安装的Docker版本就是旧版本,旧版本的Docker称为 docker 或 docker-engine ,由于不在维护,故建议跳过直接安装新版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
#1、检查内核版本,必须是3.10及以上
$ uname -r
#2、安装docker
$ yum install docker -y
#3、启动docker
$ systemctl start docker
$ docker -v
Docker version 1.12.6, build 3e8e77d/1.12.6
#4、开机启动docker
$ systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
#5、停止docker
$ systemctl stop docker

2. 安装新版本

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
#卸载旧版本,如果已安装这些程序,请卸载它们以及相关的依赖项
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

#安装新版yum源
$ sudo yum-config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo

#更新yum软件源缓存,并安装docker-ce。
$ sudo yum makecache fast
$ sudo yum install docker-ce -y

#验证安装是否成功(有client和service两部分表示docker安装启动都成功了)
$ docker version

#启动并加入开机启动
$ sudo systemctl start docker
$ sudo systemctl enable docker

更多内容:

查看所有仓库中所有docker版本:yum list docker-ce --showduplicates | sort -r

安装指定版本:比如sudo yum install docker-ce-17.12.0.ce

新版docker安装好后命令自动补全会有些缺失,所以可以选择安装命令补全依赖工具。

1
2
3
4
5
6
#docker自动补齐需要依赖工具bash-complete,安装好后会得到文件为 /usr/share/bash-completion/bash_completion
$ sudo yum install -y bash-completion

#装好docker自动补齐依赖之后,要刷新下才能让其生效
$ sudo source /usr/share/bash-completion/bash_completion
$ sudo source /usr/share/bash-completion/completions/docker

四、镜像下载加速

鉴于国内网络问题,Docker默认是从官方Docker Hub拉取 Docker 镜像十分缓慢,我们可以需要配置加速器来解决。

测速:https://github.com/docker-practice/docker-registry-cn-mirror-test/actions

编辑 /etc/docker/daemon.json(Linux) 或者 %programdata%\docker\config\daemon.json(Windows) 来配置 Daemon(如果文件不存在请新建该文件)。

1
$ vim /etc/docker/daemon.json

添加以下内容:

1
2
3
4
5
6
{
"registry-mirrors": [
"https://dockerhub.azk8s.cn",
"https://hub-mirror.c.163.com"
]
}

可以配置多个加速镜像。由于镜像服务可能出现宕机,建议同时配置多个加速镜像。

1
2
3
4
5
6
#重新加载配制
$ systemctl daemon-reload
#重启docker
$ service docker restart
#检查加速器是否生效
$ docker info

如果方便建议使用aliyun的镜像

地址:https://cr.console.aliyun.com/cn-shenzhen/instances/mirrors

image-20200216144500211

五、镜像操作

https://hub.docker.com/

1
2
3
4
5
6
7
8
#检索	(去https://hub.docker.com上查看镜像的详细信息。eg:docker search redis)
$ docker search 镜像关键字
#拉取 (name是镜像名,:tag是可选的,tag表示标签,多为软件的版本,默认是latest)
$ docker pull name[:tag]
#列出 (查看所有本地镜像)
$ docker images
#删除 (删除指定的本地镜像,image-id是镜像id)
$ docker rmi image-id

六、容器操作

hell1555649048589

强制删除当前所有容器:docker rm -f $(docker ps -a -q)

小案例:

1
2
$ docker pull hello-world
$ docker run hello-world

七、综合案例

步骤:软件镜像(安装程序)—> 运行镜像 —> 产生一个容器(正在运行的软件)。

1. 安装nginx

1
2
3
4
5
6
7
8
9
10
11
12
#拉取(下载)镜像
$ docker pull hub.c.163.com/library/nginx:latest

#根据镜像实例化一个容器并运行,运行好后访问http://192.168.222.131:8080
$ docker run -d --name nginx1 -p 8080:80 nginx

#可以进入容器内部执行命令(里面的文件系统和原生linux的一样)
$ docker exec -it nginx1 bash
#在容器里执行命令查看nginx命令的位置
$ which nginx
#退出容器
$ exit

2. 安装tomcat

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
#1、搜索镜像
$ docker search tomcat

#2、拉取(下载)镜像
#$ docker pull tomcat
#这里使用的是网易镜像站的,网址:https://c.163yun.com/hub#/home
$ docker pull hub.c.163.com/library/tomcat

#3、根据镜像实例化一个容器并运行
# 选项:-d:表示后台运行;-p: 表示将主机的端口映射到容器的一个端口,如-p 主机端口:容器内部的端口。
# 启动一个做了端口映射的tomcat,假设虚拟机ip为192.168.222.132,那么启动容器后访问http://192.168.222.132:8080
$ docker run -d --name mytomcat -p 8080:8080 hub.c.163.com/library/tomcat

#4、查看运行中的容器
$ docker ps

#5、查看当前所有容器
$ docker ps -a

#6、 停止运行中的容器
$ docker stop mytomcat

#7、启动容器
$ docker start mytomcat

#8、删除一个容器(需要先停止运行中的容器)
$ docker rm mytomcat

#9、查看容器的日志 docker logs container-name或者container-id
$ docker logs mytomcat

更多命令参看https://docs.docker.com/engine/reference/commandline/docker/可以参考每一个镜像的文档

3. 安装mysql

(1)获取镜像

1
2
docker pull mysql
#docker pull mysql:5.7 #指定版本用 :标签(版本号)

(2)启动镜像

1
2
3
4
5
6
#简单方式
$ docker run --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d mysql

#做端口映射的启动方式:
$ docker run -p 3306:3306 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 -d mysql
#docker run -p 3306:3306 --name mysql5_7 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

几个其他的高级操作

1
2
3
4
5
6
$ docker run --name mysql03 -v /conf/mysql:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#把主机的/conf/mysql文件夹挂载到 mysqldocker容器的/etc/mysql/conf.d文件夹里面
#改mysql的配置文件就只需要把mysql配置文件放在自定义的文件夹下(/conf/mysql)

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
#指定mysql的一些配置参数

4. 安装rabbitmq

(1)获取镜像

1
2
#该版本包含了web控制页面
docker pull rabbitmq:management

(2)运行镜像

1
2
3
4
5
#方式一:默认用户名和密码都是guest
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management

#方式二:设置用户名和密码
docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq:management

(3)访问rabbitmq管理页面页面 http://ip:15672

八、构建自定义镜像

方式1:上传程序到vps后构建

需求:构建一个能在tomcat容器里运行的war包程序镜像,并通过镜像创建一个实例容器。

由于依赖于tomcat容器,故需要先拉去tomcat镜像到本地。tomcat镜像主页:https://c.163yun.com/hub#/library/repository/info?repoId=3105

(1)拉取tomcat镜像到宿主机

1
$ docker pull hub.c.163.com/library/tomcat:latest

(2)上传war包

创建一个webdemo项目,并在这个webdemo项目的资源路径里添加一个index.jsp页面。

1
2
3
4
5
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

然后打包得到webdemo.war文件。并上传这个webdemo.war文件到vps的/root/project目录

(3)编写Dockerfile文件

1
2
#在/root/project下编写一个Dockerfile文件
$ vim Dockerfile
1
2
3
4
5
6
#继承于某个镜像
from hub.c.163.com/library/tomcat
#镜像所有者信息
MAINTAINER qcmoke qcmoke@gmail.com
#把程序copy到容器镜像当中,前面的参数是本地路径,后面的参数是容器镜像路径(可以到镜像主页得到tomcat的webapp路径)
COPY /root/project /usr/local/tomcat/webapps

(4)构建生成镜像

1
2
#在Dockerfile文件所在的目录,即/root/project里执行如下命令
$ docker build -t webdemo:latest .

(5)查看本地镜像仓库是否构建成功

1
$ docker images
1
2
3
REPOSITORY                     TAG                 IMAGE ID            CREATED                  SIZE
docker.io/tomcat latest aeea3708743f Less than a second ago 529 MB
webdemo latest 10f75818641a 46 seconds ago 310 MB

(6)通过构建的镜像实例化一个容器并运行

1
$ docker run -d -p 8080:8080 webdemo:latest

(7)访问测试

访问index.jsp:http://192.168.222.131:8080/webdemo/index.jsp

image-20200215111413522

(8)其他

在用-d指定为后台启动的情况下,可以使用以下命令查看容器实时的日志情况:

1
$ docker logs -f 容器名称或者容器id

方式2:通过idea插件连接vps构建

(1)配置docker允许外网访问

在vps中配置docker允许外网访问

1
$ vim /usr/lib/systemd/system/docker.service

ExecStart属性原来值的最后追加

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

新版Docker CE配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
....
....
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
....
....

旧版Docker配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Service]
....
....
ExecStart=/usr/bin/dockerd-current \
--add-runtime docker-runc=/usr/libexec/docker/docker-runc-current \
--default-runtime=docker-runc \
--exec-opt native.cgroupdriver=systemd \
--userland-proxy-path=/usr/libexec/docker/docker-proxy-current \
--init-path=/usr/libexec/docker/docker-init-current \
--seccomp-profile=/etc/docker/seccomp.json \
$OPTIONS \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$ADD_REGISTRY \
$BLOCK_REGISTRY \
$INSECURE_REGISTRY \
$REGISTRIES \
-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
....
....

(2)重新加载配置并重启Docker

1
2
$ systemctl daemon-reload
$ systemctl restart docker

(3)启动防火墙并开放2375端口

开放了防火墙2375端口用于远程连接

1
2
3
4
$ service firewalld start
$ firewall-cmd --permanent --add-port=2375/tcp
$ firewall-cmd --reload
$ firewall-cmd --list-all
  • 不需要另外开放容器映射到宿主机的端口。
  • 经操作发现,如果使用vmware的linux作为vps,不能直接关闭防火墙,开放相应的端口即可。

(4)创建一个springboot项目

image-20200216133115274

pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo-boot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--将其他模块的依赖一起打包生成可执行jar-->
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

DemoApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author qcmoke
*/
@RestController
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

@RequestMapping("/hello")
public Object hello() {
return "hello docker!";
}
}

application.yml

1
2
server:
port: 8080

Dockerfile

1
2
3
4
5
6
7
8
9
FROM openjdk:8u212-jre
#存放持久化数据的目录
VOLUME /tmp
#要复制到容器中的问件
ADD target/demo-boot-0.0.1-SNAPSHOT.jar /demo-boot.jar
#docker容器启动时执行的命令
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/demo-boot.jar"]
#启动端口号(容器中的)
EXPOSE 8080

(5)编译项目生成jar包

image-20200216134810561

(6)配置远程docker插件连接

默认新版的idea自带有这个插件,如果没有直接到插件中心安装即可。

image-20200216133850397

(7)然后配置DockerFile

image-20200216132351344

image-20200216134320278

(8)运行docker插件

运行插件部署镜像到vps,并通过镜像创建一个实例容器

image-20200216140432811

(9)访问测试

最后访问: http://192.168.222.132:8080/hello

image-20200216141102237

九、docker compose

1. 简介

Compose项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。

地址:https://github.com/docker/compose

使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。Compose 允许用户通过一个单独的 docker-compose.yml 模板文件来定义一组相关联的应用容器为一个项目。

2. 安装

在 Linux 上的也安装十分简单,从 官方 GitHub Release 处直接下载编译好的二进制文件即可。

例如,在 Linux 64 位系统上直接下载对应的二进制包。

1
2
3
4
5
$ sudo curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

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

$ docker-compose --version

3. 卸载

如果是二进制包方式安装的,删除二进制文件即可。

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

4. 编排文件

在任意目录创建compose编排配置文件: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
33
34
35
36
37
## docker-compose.yml文件的版本
version: '3.1'
services: # compose管理的服务
redis:
image: redis # 指定镜像
container_name: redis-1 # 容器名称
restart: always # 开机自动启动
ports: # 端口映射
- 6379:6379
volumes: # 目录映射
- /micro-cloud-erp/redis/conf:/usr/local/etc/redis
- /micro-cloud-erp/redis/data:/data
command: redis-server --requirepass qcmoke123456 --appendonly yes #执行的命令; requirepass来指定远程登录密码; appendonly来指定是否开启持久化策略
#command: redis-server /usr/local/etc/redis/redis.conf --appendonly yes

mysql:
image: mysql:5.7.24
container_name: mysql-1
ports:
- 3306:3306
environment: # 环境变量
MYSQL_ROOT_PASSWORD: qcmoke123456 # 设置数据库root密码
restart: always
volumes:
- /micro-cloud-erp/mysql/data:/var/lib/mysql
#当 MySQL 服务启动时会以/etc/mysql/my.cnf为配置文件,而该文件会导入/etc/mysql/conf.d目录中所有以.cnf为后缀的文件。
#这些文件会拓展或覆盖 /etc/mysql/my.cnf 文件中的配置。因此创建以.cnf结尾的配置文件并挂载至MySQL容器中的/etc/mysql/conf.d目录即可。
#在本项目中只要在docker-compose up前上传my.cnf文件到宿主机的/micro-cloud-erp/mysql/conf.d/my.cnf目录即可。如果在docker-compose up后的话,需要重启mysql容器才能重新加载到自定义的配置文件。
- /micro-cloud-erp/mysql/conf.d:/etc/mysql/conf.d

nacos:
image: nacos/nacos-server
container_name: nacos-standalone
environment:
- MODE=standalone
ports:
- 8848:8848

下面是compose编排配置文件中使用到的mysql配置文件:my.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8

[mysqld]
# 设置3306端口
port = 3306
# 设置mysql的安装目录
# basedir=/var/lib/mysql
# 设置 mysql数据库的数据的存放目录,如果是MySQL 8+ 不需要以下配置,系统自己生成即可,否则有可能报错
# datadir=/var/lib/mysql/data
# 允许最大连接数
max_connections=20
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 最大连接数
max_connections=500

5. 操作命令

docker-compose.yml所在的目录执行如下命令

1
2
3
4
5
6
7
8
#尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。相关的服务都将会被自动启动,除非已经处于运行状态。
$ docker-compose up
#以守护进程模式运行加-d选项
$ docker-compose up -d
#此命令将会停止 up 命令所启动的容器,并移除网络
$ docker-compose down
#重启项目中的服务。
$ docker-compose restart [options] [SERVICE...]

十、Docker Swarm

Docker Swarm 是 Docker 的集群管理工具。swarm 集群由管理节点(manager)和工作节点(work node)构成。

swarm mananger:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作。

work node:即图中的 available node,主要负责运行相应的服务来执行任务(task)。

注意:跟集群管理有关的任何操作,都是在管理节点上操作的。

准备6台linux服务器

manager-1:192.168.99.101

manager-2:192.168.99.102

manager-3:192.168.99.103

worker-1:192.168.99.201

worker-2:192.168.99.202

worker-3:192.168.99.203

1. 关闭所有服务器的防火墙

1
$ service firewalld stop

2. 初始化 swarm 集群

进行初始化的这台机器,就是集群的管理节点。

1
$ docker swarm init --advertise-addr 192.168.68.101

eg:

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# docker swarm init --advertise-addr 192.168.68.101
Swarm initialized: current node (w7xdf6see52t2t24x1ykedg5o) is now a manager.

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

docker swarm join \
--token SWMTKN-1-04sl6nb0acbzzgvfrqycph4jtnyh0wcoix70gz44sjuaf66cwd-3xqtzzxymio3077xfki41od0e \
192.168.68.101:2377

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

3. 添加worker节点

在manager节点下生成worker令牌,以让其他worker服务器加入

1
$ docker swarm join-token worker

eg:

1
2
3
4
5
6
[root@localhost ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-04sl6nb0acbzzgvfrqycph4jtnyh0wcoix70gz44sjuaf66cwd-3xqtzzxymio3077xfki41od0e \
192.168.68.101:2377

然后在三台worker节点运行:

1
2
3
$ docker swarm join \
--token SWMTKN-1-04sl6nb0acbzzgvfrqycph4jtnyh0wcoix70gz44sjuaf66cwd-3xqtzzxymio3077xfki41od0e \
192.168.68.101:2377

4. 添加manager节点

在manager节点下生成manager令牌,以让其他manager服务器加入

1
$ docker swarm join-token manager

eg:

1
2
3
4
5
6
[root@localhost ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:

docker swarm join \
--token SWMTKN-1-04sl6nb0acbzzgvfrqycph4jtnyh0wcoix70gz44sjuaf66cwd-4nbcolan6w4akrs3zsbvrkqxe \
192.168.68.101:2377

然后在三台manager节点运行如下命令:

1
2
3
$ docker swarm join \
--token SWMTKN-1-04sl6nb0acbzzgvfrqycph4jtnyh0wcoix70gz44sjuaf66cwd-4nbcolan6w4akrs3zsbvrkqxe \
192.168.68.101:2377

5. 查看所有管理的节点

manager-1运行命令查看所有管理的节点

1
$ docker node ls

eg:

1
2
3
4
5
6
7
8
[root@localhost ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
dif8w8hp6pevz9k0owqkg6hjl localhost.localdomain Ready Active
j9jqdioy91olyxd8dfghgm8qc localhost.localdomain Ready Active
mfv24dim85bi7sd9wl589rhdf localhost.localdomain Ready Active Reachable
q1qayx19ebfg7oi8dv7e3mzyh localhost.localdomain Ready Active
rbeb5mykx83qpr6u8afriqx9z localhost.localdomain Ready Active Reachable
w7xdf6see52t2t24x1ykedg5o * localhost.localdomain Ready Active Leader

6. 创建集群服务

1
$ docker service create -p 80:80 --name my-nginx nginx

这时候将会在任意节点中选择一台通过docker创建nginx服务。我们可以在集群下任意一台服务器(manager或者worker节点)访问nginx服务都能访问到,因为swarm创建的服务使用的是swarm集群网络。

7. 查看服务集群情况

1
$ docker service ls

eg:

1
2
3
[root@localhost ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
v1hn945nmyds my-nginx replicated 1/1 nginx:latest

REPLICAS:副本数量

8. 集群服务扩容

对my-nginx服务扩容为5个

第一种方式:

1
$ docker service update --replicas 5 my-nginx

eg:

1
2
3
4
5
[root@localhost ~]# docker service update --replicas 5 my-nginx
my-nginx
[root@localhost ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
v1hn945nmyds my-nginx replicated 5/5 nginx:latest

第二种方式:

1
$ docker service scale my-nginx=5
1
2
3
4
5
[root@localhost ~]# docker service scale my-nginx=5
my-nginx scaled to 5
[root@localhost ~]# docker service ls
ID NAME MODE REPLICAS IMAGE
v1hn945nmyds my-nginx replicated 5/5 nginx:latest

update更多的应用场景在于image的升级导致的运行中的服务需要更新等等

9. 删除集群服务

1
$ docker service rm my-nginx

这时候所有副本都会被删除

10. 修改服务

比如修改nginx服务镜像版本为1.9.5

1
$ docker service update --image nginx:1.9.5 my-nginx
1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
kzg8qncaal9a my-nginx.1 nginx:1.9.5 localhost.localdomain Running Running about a minute ago
er55pvmd8fn6 \_ my-nginx.1 nginx:latest localhost.localdomain Shutdown Shutdown about a minute ago
kv3t6poxh3rb my-nginx.2 nginx:1.9.5 localhost.localdomain Running Running about a minute ago
tuzkxmb0th6x \_ my-nginx.2 nginx:latest localhost.localdomain Shutdown Shutdown about a minute ago
edt0tg6tg120 my-nginx.3 nginx:1.9.5 localhost.localdomain Running Running about a minute ago
qfwlzj8hb3gl \_ my-nginx.3 nginx:latest localhost.localdomain Shutdown Shutdown about a minute ago
bb9kjj3n81yx my-nginx.4 nginx:1.9.5 localhost.localdomain Running Running about a minute ago
spx8ybz9wlph \_ my-nginx.4 nginx:latest localhost.localdomain Shutdown Shutdown about a minute ago
vs4akco7zpls my-nginx.5 nginx:1.9.5 localhost.localdomain Running Running about a minute ago
qtaqq0jout6k \_ my-nginx.5 nginx:latest localhost.localdomain Shutdown Shutdown about a minute ago

11. 服务回滚

1
$ docker service update --rollback

十一、问题排错

(1)Error response from daemon: oci runtime error: container_linux.go:247: start....,原因是系统和docker版本不兼容。解决:执行yum update

(2)rying to pull repository docker.io/library/mysql ... Get https://registry-1.。解决:执行以下命令:

1
2
3
4
$ yum install bind-utils     #安装dig工具
$ dig @114.114.114.114 registry-1.docker.io
$ vi /etc/hosts
52.54.155.177 registry-1.docker.io

(3)[root@izuf6dskn3b7v2sly08bqtz ~]# docker pull mysql Using default tag: latest Trying to pull repository docker.io/library/mysql ... Get https://registry-1.docker.io/v2/: x509: certificate is valid for *.theranest.com, theranest.com, not registry-1.docker.io

解决:镜像加速解决

(3)执行docker-compose up -d后出现错误:ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-950144d461c2 -j RETURN: iptables: No chain/target/match by that name. (exit status 1))

重启docker试试

1
2
$ systemctl stop docker
$ systemctl start docker

十二、参考

📚《Docker — 从入门到实践》



----------- 本文结束 -----------




如果你觉得我的文章对你有帮助,你可以打赏我哦~
0%