一.Docker概述与安装

开发一个新项目后,会涉及到环境部署的问题(如MySQL、Redis等),会耗费比较多时间,因此急需一种可以快速打包部署项目并上线的方法。

Docker(一种容器化技术)因此而生。它的思想是隔离,将项目与环境进行打包、装箱,将服务器性能利用到极致。

官方文档:https://docs.docker.com/

Docker 和 虚拟机技术有何不同?

  • 传统虚拟机是虚拟出一套硬件,运行一个完整的操作系统,并在操作系统上安装应用

  • Docker容器内应用直接运行在宿主机内核(共享内核),容器相互隔离互不影响

    Docker 虚拟机
    操作系统 与宿主机共享OS 宿主机OS上运行虚拟机OS
    存储大小 镜像小,便于存储和传输 镜像庞大(vmdk vdi等)
    运行性能 几乎无额外性能损失 操作系统额外的CPU、内存消耗
    移植性 轻便、灵活、适用于Linux 笨重,与虚拟化技术耦合度高
    硬件亲和性 面向软件开发者 面向硬件运维者

Docker架构

镜像(image):类似一个模板,可以通过模板来创建容器服务。通过一个镜像可以创建多个容器。它是一种轻量级、可执行的独立软件包,包含运行软件所需的运行时、库、环境变量和配置环境等。

容器(container):独立运行一个或一组应用,可以理解为一个简易的linux系统

仓库(repository):存放镜像的位置

Docker安装

环境查看

1
2
3
4
5
6
# 系统内核
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# uname -r
3.10.0-1127.10.1.el7.x86_64

# 系统版本
[root@iZ2ze7qxbl1r54zhx9fbs3Z /]# cat /etc/os-release

安装帮助文档:https://docs.docker.com/engine/install/

按照文档安装完成后

1
2
3
4
5
6
7
8
9
10
11
# 启动Docker
systemctl start docker

# 查看版本
docker version

# 运行hello-world
docker run hello-world

# 查看镜像
docker images

配置阿里云镜像加速服务(控制台->产品与服务->弹性计算->容器镜像服务->镜像加速器)

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://7nonk1j6.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

二.Docker常用命令

帮助命令

1
2
3
4
docker version  # 查看docker版本信息
docker info # 显示docker的信息,包括镜像、容器数量
docker help # 帮助
docker 命令 --help

官方文档:https://docs.docker.com/engine/reference/run/

镜像命令

docker images:查看本地主机上的镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 7 months ago 13.3kB

# 说明
REPOSITORY 镜像的仓库源
TAG 镜像标签
IMAGE ID 镜像ID
CREATED 镜像创建时间
SIZE 镜像大小

# 常用可选项
-a , --all # 列出所有镜像
-q , --quiet # 只显示镜像ID

docker search:搜索镜像

1
2
3
4
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker search mysql

# 常用可选项,使用filter限制搜索条件(例如下方搜索3000赞以上的镜像)
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker search mysql --filter=STARS=3000

docker pull:下载镜像

1
2
# 如果不写tag默认latest
docker pull 镜像名[:tag] # 例如 docker pull mysql:5.7

docker rmi:删除镜像

1
2
docker rmi -f 镜像ID或镜像名
docker rmi -f $(docker images -aq) # 删除全部镜像

容器命令

首先,下载一个centos镜像进行测试

1
docker pull centos

新建容器并启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
docker run [参数] image

# 常用参数
--name # 容器名
--detach # 后台方式运行 -d
-it # 使用交互方式运行
-p # 指定容器端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口
-p 容器端口
-P # 随机指定端口(大写)

# 启动并进入容器
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker run --it centos /bin/bash
# 退出容器
[root@274f17eaf88a /]# exit

# 查看正在运行容器
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker ps
-a # 列出历史+现在正在运行的容器
-n=? # 显示最近个数
-q # 只显示容器ID

退出容器

1
2
exit  # 容器停止并退出
Ctrl+P+Q # 容器不停止并退出

删除容器

1
2
docker rm 容器ID	# 删除容器
docker rm -f $(docker ps -aq) # 删除所有容器

启动与停止容器

1
2
3
4
docker start 容器ID    # 启动
docker restart 容器ID # 重启容器
docker stop 容器ID # 停止容器
docker kill 容器ID # 强制停止

其他命令

后台启动容器

1
2
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker run -d centos
# 注意:使用后台运行,需要有一个前台进程,否则会自动停止

日志查看

1
2
3
# docker logs -tf --tail 条数 容器ID
# -t为显示时间戳, -f为跟踪日志输出
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker logs -tf --tail 10 f6baeea082b1

查看容器中进程信息

1
2
# docker top 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker top f6baeea082b1

查看镜像数据源

1
2
# docker inspect 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker inspect f6baeea082b1

进入当前正在运行容器

1
2
3
4
# docker exec -it 容器ID /bin/bash
# docker attach 容器ID
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker exec -it f6baeea082b1 /bin/bash
[root@iZ2ze7qxbl1r54zhx9fbs3Z ~]# docker attach f6baeea082b1

从容器内拷贝文件到主机

1
docker cp 容器ID:文件路径 主机路径

三.安装练习

仓库推荐:DockerHub

可视化面板推荐:portainer

安装Nginx

1
2
3
4
5
6
7
8
9
# 1.搜索并拉取镜像
docker search nginx
docker pull nginx

# 2.新建容器并启动 -d为后台运行,名字为nginx01,本机端口3344,容器端口80
docker run -d --name nginx01 -p 3344:80 nginx

# 3.访问测试
curl localhost:3344

安装Tomcat

1
2
3
4
5
6
7
8
# 直接安装
docker run -it --rm tomcat:9.0 # 测试,用完即删

# 下载再启动
docker pull tomcat

# 启动
docker run -d --name tomcat01 -p 3345:80 tomcat

安装ES+head插件+Kibana

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 启动
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.8.1

# 注意:安装完后会发现内存占用很大,服务器十分卡顿
docker stats # 查看服务器资源状态

# 启动时限制内存在64MB-512MB -e ES_JAVA_OPTS="-Xms64m -Xmx512m"
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.8.1

# 拉取并安装head监控管理插件
docker pull mobz/elasticsearch-head:5
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5

# 安装kibana
docker run --name kibana -e ELASTICSEARCH_URL=http://39.97.107.13:9200 -p 5601:5601 -d kibana:7.8.1

四.镜像原理与数据卷

镜像加载

联合文件系统(UnionFS)

是一种分层、轻量级且高性能的文件系统,支持对文件系统的修改作为一次提交来以层层叠加。它是Docker镜像的基础。

Docker镜像加载原理

Docker镜像实际上由一层层文件系统组成,这种层级文件系统就是 UnionFS。

Q:为什么CentOS镜像那么小?

A:精简后的OS,rootfs(root file system)可以非常小,只需包含基本命令、工具和程序库。对于不同Linux发行版,bootfs(boot file system)基本一致,只是rootfs有差别。

特点

Docker镜像都是只读,当容器启动时一个新的 可写层 会被加载到镜像顶部。

这一层也被称为 容器层,容器以下的都是 镜像层

镜像提交

1
docker commit -m="描述信息" -a="作者名" 容器id 目标镜像名:[TAG]

容器数据卷

将Docker容器内产生的数据同步到本地,相当于挂载到宿主机上。这样一来,就算将容器不小心删除了,我们的数据还是能得到保存。

方法一:使用命令挂载 -v

1
2
3
4
docker run -it -v 主机目录:容器内目录 -p

# 查看挂载情况 "Mounts"属性
docker inspect 容器ID

MySQL数据挂载测试

1
2
# 启动测试 注意-e配置参数参考dockerhub
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw=123456 --name mysql01 mysql:5.7

方法二:数据卷容器

1
2
# 通过 --volumes-from 实现两个容器的数据卷同步
docker run -it --name docker-2 --volumes-from docker-1 92f4cfd1ccbe

匿名挂载与具名挂载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 匿名挂载,只写容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看卷情况
[root@iZ2ze7qxbl1r54zhx9fbs3Z /]# docker volume ls
DRIVER VOLUME NAME
local 5c0348ebc465674851391d48a81cecdd91a9f4c52ec09209a49e68ab4ce33f22

# 具名挂载 卷名:容器内路径
docker run -d -P --name nginx01 -v nginx_juan:/etc/nginx nginx

# 可以通过 ro rw 改变容器读写权限
ro readonly 只读
rw readwrite 可读写
# 例如
docker run -d -P --name nginx01 -v nginx_juan:/etc/nginx:ro nginx

DockerFile简介

它是一个构建docker镜像的文件,是命令参数脚本。

步骤:

  1. 编写一个 dockerfile 文件
  2. docker build 构建一个新镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(dockerhub、阿里云镜像仓库等)

举例

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
# 创建dockerfile
FROM centos
VOLUME ["volume01","volume02"] # 挂载目录,启动后会在根目录创建
CMD echo "---end---"
CMD /bin/bash

# 测试新建容器 -f dockerfile文件名 -t 镜像名:版本号
[root@iZ2ze7qxbl1r54zhx9fbs3Z ceshi]# docker build -f /home/ceshi/dockerfile1 -t banana_centos:1.0 .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM centos
---> 831691599b88
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 8ca74a22f596
Removing intermediate container 8ca74a22f596
---> 665e599d4961
Step 3/4 : CMD echo "---end---"
---> Running in 5a0de7cd643b
Removing intermediate container 5a0de7cd643b
---> 23d0d3685d01
Step 4/4 : CMD /bin/bash
---> Running in 84671b255a0b
Removing intermediate container 84671b255a0b
---> 92f4cfd1ccbe
Successfully built 92f4cfd1ccbe
Successfully tagged banana_centos:1.0

构建过程

基础知识:

  1. 每个关键字指令必须是大写字母
  2. 从上到下按顺序执行
  3. 注释符号是 #
  4. 每个指令都会创建一个新的镜像层

DockerFile指令与编写

1
2
3
4
5
6
7
8
9
10
11
12
FROM          # 从基础镜像开始构建
MAINTAINER # 维护者信息,姓名+邮箱
RUN # 运行的命令
ADD # 添加文件 如tomcat
WORKDIR # 设置镜像工作目录
VOLUME # 挂载的目录
EXPOSE # 指定对外端口
CMD # 容器运行时要运行的命令,只有最后一个生效
ENTRYPOINT # 容器运行时要运行的命令,可以追加命令
ONBUILD # 构建一个被继承DockerFile时会被触发
COPY # 将文件拷贝到镜像中
ENV # 设置环境变量

创建一个自己的CentOS镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1.编写dockerfile文件
FROM centos
MAINTAINER banana<798998087@qq.com>

ENV MYPATH /usr/local # 设置工作目录
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

# 2.通过文件构建镜像
docker build -f dockerfile文件名 -t 镜像名:版本号 .

创建一个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
31
32
33
# 1.准备好tomcat与jdk安装包
[root@iZ2ze7qxbl1r54zhx9fbs3Z tomcat]# ls
apache-tomcat-8.5.50.tar.gz jdk-8u241-linux-x64.tar.gz

# 2.编写文件Dockerfile(这是官方命名,用这个名字后构建镜像无需-f指定)
FROM centos
MAINTAINER banana<798998087@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u241-linux-x64.tar.gz /usr/local
ADD apache-tomcat-8.5.50.tar.gz /usr/local

RUN yum -y install vim

ENV MYPATH /usr/local
WORKDIR $MYPATH

ENV JAVA_HOME /usr/local/jdk1.8
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.50
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.50
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-8.5.50/bin/startup.sh

# 3.构建镜像
docker build -t mytomcat .

# 4.创建容器,启动(同时将目录挂载出来方便部署)
docker run -d -p 9090:8080 --name bananaTomcat -v /home/ceshi/tomcat/test:/usr/local/apache-tomcat-8.5.50/webapps/test -v /home/ceshi/tomcat/logs:/usr/local/apache-tomcat-8.5.50/logs mytomcat

发布镜像

DockerHub

https://hub.docker.com/ 注册账号后

服务器上提交镜像

1
2
3
4
5
6
7
8
9
10
11
# 登录
docker login -u 账号

# 推送镜像前要记得修改tag
docker tag 镜像ID 账号ID/镜像名:版本号

# 推送(例子)
docker push tj20185584/tomcat:1.0

# 查看仓库
https://hub.docker.com/r/tj20185584/tomcat

阿里云镜像服务

产品与服务->弹性计算->容器镜像服务->命名空间(创建)->镜像仓库(创建)

然后在镜像仓库页面中点击“管理”,查看操作指南即可

五.SpringBoot打包Docker镜像

1.将项目打包 maven package

2.在idea中安装Docker插件

3.在target文件夹内编写Dockerfile文件

1
2
3
4
5
6
7
8
9
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]

4.将jar包(或war包)和Dockerfile上传至服务器

5.打包镜像

1
docker build -t 镜像名 .

6.生成容器并运行

1
docker run -d -P --name 容器名 镜像名