Docker概括

Docker简介

(1)Docker是一个开源的应用容器引擎,解决了依赖兼容问题、解决了操作系统环境差异

(2)分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署,环境不一定一致,会遇到各种问题

Docker和虚拟机的区别

对比Docker容器虚拟机(VM)
操作系统与宿主机共享OS,系统的进程宿主机OS上运行虚拟机OS,操作系统中的操作系统
存储大小镜像小,便于存储与传输镜像庞大(vmdk、vdi等)
运行性能几乎无额外性能损失操作系统额外的CPU、内存消耗
移植性轻便、灵活、适应于linux笨重、与虚拟化技术耦合度高
硬件亲和性面向软件开发者面向硬件运维者
部署速度快速,秒级较慢,10S以上
系统支持单机支持上千个容器一般几十个

Docker架构

概念说明
Docker 镜像(Images)容器镜像是轻量级的、可执行的独立软件包,包含软件运行所需要的所有内容(代码、运行时环境、系统工具、系统库和设置) 相当于是一个root文件系统,用于创建 Docker 容器的只读模板,一个镜像可以创建很多容器
Docker 容器(Container)容器是独立运行的一个或一组应用,镜像中的应用程序,运行后形成的进程就是容器,是镜像运行时的实体
可以把容器看做是一个简易版的 Linux 环境(root用户权限、进程空间、网络空间等)和运行在其中的应用程序 Docker会给容器进程做隔离,对外不可见,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体,容器可以被创建、启动、停止、删除、暂停等
Docker 客户端(Client)Docker 客户端通过命令行或者其他工具使用 Docker SDK 与 Docker 的守护进程通信。
Docker 主机(Host)一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker 仓库(Registry)Docker镜像的托管平台,用来保存镜像,类似于Maven仓库
仓库分为公开仓库(Public)和私有仓库(Private)两种形式
最大的公开仓库是 Docker Hub(https://hub.docker.com/)
国内也有类似于DockerHub 的公开服务,如网易云镜像服务、阿里云镜像库等。
Docker 命令行工具(Machine)Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行,即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure。

Docker安装与使用

准备工作

(1)Docker 分为 CE 和 EE 两大版本,Docker 必须部署在linux内核的系统上

版本区别
CE社区版,免费,支持周期 7 个月,分为 stable testnightly 三个更新频道
EE企业版,强调安全,付费使用,支持周期 24 个月

(2)CentOS 仅发行版本中的内核支持 Docker,Docker 运行在CentOS 7 (64-bit)上,要求系统为64位、Linux系统内核版本为 3.8以上,使用如下命令查看自己的内核,打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)

1
2
3
4
# 查看自己的内核
cat /etc/redhat-release
# 打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)
uname -r

Docker卸载(可选)

1
2
3
4
5
6
7
8
9
10
11
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce

Docker CE安装

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
#(1)安装yum工具,yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2 --skip-broken

#(2)更新yum到最新,更新XFS文件系统管理工具
yum update
yum update xfsprogs -y

#(3)设置yum的docker源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

#(4)解决域名问题
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

#(5)更新镜像源缓存
yum makecache fast

#(6)安装docker-ce社区免费版本,出现输入的界面都按 y
yum install -y docker-ce

#(7)查看docker版本,验证是否成功
docker -v

#(8)关闭防火墙后,再启动docker
systemctl stop firewalld
systemctl disable firewalld.service
systemctl start docker

配置阿里云镜像加速器

(1)默认情况下,将从docker hub上下载docker镜像,由于太慢所以一般都会配置镜像加速器

(2)进入阿里云官网,注册账号或使用淘宝账号登录

(3)点击镜像服务

(4)查看操作文档

(5)复制到linux运行

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://iprigprk.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

(6)查看是否成功

1
cat /etc/docker/daemon.json

Docker常用命令

服务相关命令

命令作用
systemctl start docker启动Docker服务
systemctl stop docker停止Docker服务
systemctl restart docker重启Docker服务
systemctl status docker查看Docker服务状态
systemctl enable docker开启自启动Docker服务

镜像相关命令

命令作用
docker images [-q/-a]查看镜像
参数-a:列出本地所有的镜像(含历史映像层)
参数-q:只显示镜像ID
docker search [–limit N] 镜像名称搜索镜像,从网络中查找需要的镜像
参数–limit N:只列出N个镜像,默认25个
docker pull 镜像名称:版本号拉取镜像,从Docker 仓库下载镜像到本地,不指定版本号则是最新版本
如果不知道镜像版本,可以去https://hub.docker.com/搜索对应镜像查看
docker save 镜像名 > xxx.tar导出镜像,将镜像导出到磁盘为tar包
docker load -i xxx.tar加载镜像,从一个存储文件或一个标准输入流中加载一个镜像
docker rmi 镜像id或镜像名称:版本号 [-f/-q]删除镜像,删除本地镜像
参数-f:删除多个镜像
参数-q:删除所有本地镜像

容器相关命令

命令作用
docker ps [-a]查看正在运行的容器
参数-a:列出当前所有正在运行的容器+历史上运行过的
参数-l:显示最近创建的容器
参数-n:显示最近n个创建的容器
参数-q:静默模式,只显示容器编号
docker run [参数] 镜像名或id:版本号 /bin/bash创建容器,有镜像才能创建容器
参数-i:以交互模式运行容器,通常与-t同时使用
参数-t:为容器重新分配一个伪输入终端,通常与-i同时使用
参数-d:创建一个容器以守护模式运行容器(后台运行)
参数-v:本地工作目录:docker工作目录
参数-P:随机端口映射,大写P
参数-p:指定端口映射,小写p
参数-it:创建交互式容器,退出容器后,容器自动关闭
参数-id:创建守护式容器,退出容器后,容器不会关闭
参数–net:网桥名字
参数–ip:分配各容器的IP
参数–name:为创建的容器命名
参数–restart:重启的策略,在容器退出时总是重启容器
参数–runtime=nvidia:使用显卡就添加,不用可以不添加
docker exec -it 容器名称或id /bin/bash进入容器(退出容器中的,容器不会关闭)
docker stop 容器名称或id停止容器
docker kill 容器ID或容器名强制停止容器
docker start 容器名称或id启动容器
docker rm 容器名称或id删除已经停止的容器,容器运行状态会删除失败,需要停止容器才能删除
docker inspect 容器名称或id查看容器信息
docker cp 容器ID:容器内路径 目的主机路径从容器内拷贝文件到主机上
cat 文件名.tar | docker import - 镜像用户/镜像名:镜像版本号从tar包中的内容创建一个新的文件系统再导入为镜像
docker export 容器ID > 文件名.tar导出容器的内容留作为一个tar归档文件
exit退出容器,容器停止
ctrl+p+q退出容器,容器不停止

端口映射

容器内的网络服务和外部机器不能直接通信,但是外部机器和宿主机可以直接通信,宿主机和容器可以直接通信,当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射到宿主机的端口上,外部机器访问宿主机的端口,从而间接访问容器的服务,这种操作称为端口映射,端口映射通过-p参数设置

Docker常见应用部署

MySQL部署

(1)搜索、下载镜像

1
2
3
4
5
6
7
8
9
#(1)搜索MySQL镜像
[root@linux docker]# docker search mysql

#(2)拉取MySQL镜像
[root@linux docker]# docker pull mysql:5.7

#(3)在随意目录下创建mysql目录用于存储mysql数据信息
[root@linux docker]# mkdir mysql5.7
[root@linux mysql5.7]# cd mysql5.7

(2)创建容器,设置端口映射、目录映射

1
2
3
4
5
6
7
8
docker run -id \
--name=container_mysql \
-p 3307:3306 \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7
参数简介
-p 3307:3306宿主机端口:容器端口,将宿主机的3307端口与容器的3306端口映射,实际开发要映射3306端口
$PWD表示执行了pwd获取到了当前路径
–v $PWD/conf:/etc/mysql/conf.d将主机当前目录下的conf/my.cnf挂载到容器/etc/mysql/my.cnf配置目录
-v $PWD/logs:/logs将主机当前目录下的logs目录挂载到容器的/logs目录日志
-v $PWD/data:/var/lib/mysql将主机当前目录下的data目录挂载到容器的/var/lib/mysql数据目录
-e MYSQL_ROOT_PASSWORD=123456初始化root 用户密码

(3)进入容器登录MySQL

1
2
3
4
# 进入容器
[root@linux mysql5.7]# docker exec -it container_mysql /bin/bash
# 登录MySQL
root@c59ff4921485:/# mysql -uroot -p123456

Tomcat部署

(1)搜索、下载镜像

1
2
3
4
5
6
7
8
9
#(1)搜索Tomcat镜像
[root@linux docker]# docker search tomcat

#(2)拉取Tomcat镜像
[root@linux docker]# docker pull tomcat

#(3)在随意目录下创建Tomcat目录用于存储Tomcat数据信息
[root@linux docker]# mkdir tomcat
[root@linux tomcat]# cd tomcat

(2)创建容器,设置端口映射、目录映射

1
2
3
4
5
docker run -id \
--name=container_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
参数简介
-p 8080:8080宿主机端口:容器端口,将宿主机的8080端口与容器的8080端口映射
$PWD表示执行了pwd获取到了当前路径
-v $PWD:/usr/local/tomcat/webapps将主机中当前目录挂载到容器的webapps

(3)创建dist目录,目录下创建index.html

1
2
3
[root@linux tomcat]# mkdir dist
[root@linux tomcat]# cd dist/
[root@linux dist]# vim index.html

(4)使用外部机器访问tomcat:http://192.168.10.100:8080/dist/index.html

Nginx部署

(1)搜索、下载镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#(1)搜索Tomcat镜像
[root@linux docker]# docker search nginx

#(2)拉取Tomcat镜像
[root@linux docker]# docker pull nginx

#(3)在随意目录下创建nginx目录用于存储nginx数据信息
[root@linux docker]# mkdir nginx
[root@linux docker]# cd nginx

#(4)创建nginx配置文件
[root@linux nginx]# mkdir conf
[root@linux nginx]# cd conf/
[root@linux conf]# vim nginx.conf
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
user  nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

include /etc/nginx/conf.d/*.conf;
}

(2)回到nginx目录,创建容器,设置端口映射、目录映射

1
2
3
4
5
6
7
docker run -id \
--name=container_nginx \
-p 80:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
参数简介
-p 80:80宿主机端口:容器端口,将宿主机的80端口与容器的80端口映射
$PWD表示执行了pwd获取到了当前路径
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf将主机当前目录下的/conf/nginx.conf挂载到容器的:/etc/nginx/nginx.conf配置目录
-v $PWD/html:/usr/share/nginx/html将主机当前目录挂载到容器的/val/log/nginx日志目录

(3)进入html目录,创建index.html

1
2
[root@linux nginx]# cd html/
[root@linux html]# vim index.html

(4)使用外部机器访问nginx:http://192.168.10.100:80/index.html

Redis部署

(1)搜索、下载镜像

1
2
3
4
5
6
7
8
9
#(1)搜索Tomcat镜像
[root@linux docker]# docker search redis

#(2)拉取Tomcat镜像
[root@linux docker]# docker pull redis:6

#(3)在随意目录下创建Tomcat目录用于存储Tomcat数据信息
[root@linux docker]# mkdir redis6
[root@linux docker]# cd redis6

(2)创建容器,设置端口映射、目录映射

1
2
3
4
docker run -id \
--name=container_redis \
-p 6379:6379 \
redis:6
参数简介
-p 6379:6379宿主机端口:容器端口,将宿主机的6379端口与容器的6379端口映射
$PWD表示执行了pwd获取到了当前路径

(3)使用外部机器连接redis

Dockerfile镜像脚本化

Dockerfile简介

Dockerfile 是用来构建Docker镜像的文本文件,包含了一条条构建镜像所需的指令(Instruction),每一条指令构建一层Layer,基于基础镜像,最终构建出一个新的镜像

Dockerfile脚本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 定义父镜像
FROM <基础镜像名称>:<基础镜像标签>
# 定义作者信息
LABEL maintainer="<作者信息>"
# 定义默认的工作目录
WORKDIR /app
# 复制文件到容器中
COPY <本地文件路径> <容器目录>
# 执行命令
RUN <命令>
# 暴露端口
EXPOSE <端口号>
# 定义容器启动执行的命令
CMD ["<启动命令>"]

执行 Dockerfile 文件构建镜像的命令

1
docker build -t <镜像名称>:<标签> <Dockerfile所在目录路径>

Dockerfile关键字

关键字作用语法
FROM指定基础镜像(父镜像)FROM <镜像>
MAINTAINER作者信息MAINTAINER <名字>
LABEL标签LABEL <键>=<值> <键>=<值> …
RUN执行命令RUN [“<命令>”, “<参数1>”, “<参数2>”…]
CMD容器启动命令CMD [“<命令>”, “<参数1>”, “<参数2>”…]
ENTRYPOINT入口ENTRYPOINT [“<命令>”, “<参数1>”, “<参数2>”…]
COPY复制文件COPY <源路径> <目标路径>
ADD添加文件ADD <源路径> <目标路径>
ENV环境变量ENV <键> <值>
ARG构建参数ARG <键> <默认值>
VOLUME定义外部可以挂载的数据卷VOLUME <路径>
EXPOSE暴露端口EXPOSE <端口号>
WORKDIR工作目录WORKDIR <路径>
USER指定执行用户USER <用户名>
HEALTHCHECK健康检查HEALTHCHECK [选项] CMD <命令>
ONBUILD触发器ONBUILD <命令>
STOPSIGNAL发送信息量到宿主机STOPSIGNAL <信号>
SHELL指定执行脚本的shellSHELL [““, “-c”]

DockerCompose服务编排

Docker Compose 简介

Docker Compose 是 Docker 官方提供的一个工具,用于简化容器编排过程。它通过编写 YAML 文件来定义和管理多个 Docker 容器,并可以在多个容器间进行链接、通信和数据共享

Docker Compose 安装

(1)在官网上下载最新版本的 Docker Compose

1
2
# 注意将 {VERSION} 替换为最新版本号,也可以通过官方网站直接下载二进制文件并安装
sudo curl -L "https://github.com/docker/compose/releases/download/{VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

(2)赋予执行权限

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

(3)验证是否安装成功

1
docker-compose -version

如果出现类似以下输出,则说明已经成功安装

1
docker-compose version 1.29.0, build 07737305

Docker Compose常用命令

命令描述
docker-compose up创建并启动所有容器
docker-compose up -d在后台创建并启动所有容器
docker-compose down停止并删除所有容器
docker-compose stop停止所有容器
docker-compose start启动所有容器
docker-compose restart重启所有容器
docker-compose ps显示当前项目中正在运行的容器
docker-compose logs显示日志信息
docker-compose exec在容器内执行命令
docker-compose build构建镜像
docker-compose push将构建的镜像发布到 Docker Hub 或其他容器仓库
docker-compose config检查和显示 compose 文件的语法

Docker Compose使用案例

目录结构

1
2
3
4
5
└──redis                    # Redis 目录
├──redis # Redis 配置目录
│ ├──config # Redis 配置文件目录
│ └──redis.conf # Redis 配置文件
├──docker-compose-redis.yml # Redis Docker Compose 配置文件

Redis配置文件

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
# 开启 AOF 持久化
appendonly yes

# 指定 AOF 文件名
appendfilename "appendonly.aof"

# 指定 AOF 文件保存目录
dir /data

# 关闭 RDB 持久化
save ""
# 开启 RDB 持久化
#save 900 1
#save 300 10
#save 60 10000

# 禁用 Redis 的保护模式,允许外部连接
protected-mode no

# 允许其他服务访问
bind 0.0.0.0

# 指定 Redis 监听的端口
port 6379

# 指定日志生成的文件
#logfile /var/log/redis/redis.log

配置docker-compose-redis.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: '3'                                               # Docker Compose 版本
services:
redis:
image: redis:6.2 # Redis 镜像名称及版本号
container_name: redis # 容器名称为 'redis'
restart: unless-stopped # 容器退出时自动重启,不考虑Docker守护进程是否已停止的情况
command: [ # 启动命令
"redis-server", # 启动 Redis 服务
"/etc/redis/redis.conf ", # 使用指定的配置文件路径
"--requirepass 123456", # 添加密码为:123456,启用密码认证
"--appendonly no" # 默认不开启 AOF 持久化配置
]
environment: # 环境变量
TZ: Asia/Shanghai # 设置时区
LANG: en_US.UTF-8 # 设置语言编码
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./redis/data:/data" # 挂载本地目录 './redis/data' 到容器内部的 '/data' 目录下
- "./redis/logs:/logs" # 挂载本地目录 './redis/logs' 到容器内部的 '/logs' 目录下
- "./redis/config/redis.conf:/etc/redis/redis.conf" # 挂载本地目录 './redis/config/redis.conf' 到容器内部的 '/etc/redis/redis.conf' 文件
ports: # 映射端口
- "6379:6379" # 映射容器内部端口 6379 到主机上的端口 6379,以允许外部访问 Redis 服务

启动Redis容器

1
docker-compose -f docker-compose-redis.yml -p redis up -d

测试连接Redis

1
docker exec -it redis redis-cli -a 123456  # 密码为123456