一、为什么要学docker
高可用:系统经过专门的设计,减少服务的停工时间,保证服务的高度可用性。
高并发:对大量请求并行处理任务的能力
容错性:若服务器上某个项目出现问题,将导致该服务器上的其他服务全部受到影响
部署环境一致性:保证开发、测试、线上等环境的一致性,防止因为环境、系统及配置问题而导致的功能异常
JAVA微服务架构
#微服务之自动化部署:
Nexus + Jenkins + Git + GitLab + Docker
#微服务之日志收集与监控:
ELK + Cloud Sleuth + ZIPkin + Docker
#微服务之自动化测试与质量管理:
Nexus + Jenkins + Git + GitLab + Docker + SonarQube
#微服务之监控告警:
SpringBoot + Prometheus + grafana监控 + alertmanager + 企业微信报警 + Docker
使用Docker技术的优势
1. 快速实现对分布式微服务架构一键部署
2. 基于云计算、大数据时代,解决闲忙不均、服务资源高效利用
3. 持续集成与持续交付(CI/CD)
1.1 简化程序
docker可以让开发者打包应用以及依赖到可移植的容器中,然后发布到任何流行的Linux服务器上。比如之前要部署一套应用,需要安装系统、搭建环境、安装依赖、发布应用等操作,好比盖房子,一步步打地基,盖房子,装修。而用docker可以将已经盖好的房子打包放到口袋中,在任何地方拿出来,即可实现搬家,里面是已经配置好的如web应用、浒苔程序、文件等。方便快捷
1.2 节省开支
docker改变了高性能必然高价格的思维定式,让服务器性能得到充分利用
1.3 持续交付和部署
对开发和运维人员来说,希望的是一次性创建和配置,可以在任意地方运运行。使用docker可以定制应用镜像实现持续集成、持续交付、部署。运维人员可以直接在生产环境直接部署该镜像。
1.4 轻松的迁移
docker确保了执行环境的一致性,使得迁移变得更加容易,docker可以在很多平台运行,无论是物理机、虚拟机、公有云、私有云甚至是个人笔记本,运行结果是一致的,因此可以轻松的将平台的应用迁移到另一个平台上,而不用担心环境的变化而导致应用无法运行的情况。
1.5 docker的应用场景
web应用的自动化打包和发布
自动化测试和持续集成、发布
服务器环境中部署和调整数据库和其他后台应用
从头编译或者扩展现有的OpenShift或cloud Foundry平台来搭建自己的PasS环境
二、安装配置
2.1 Docker介绍
Docker是开源的容器化引擎,使用Go语言开发,使用Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,实现快速部署,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何影响,类似iPhone的app,重要的是容器性能开销极低。
2.2 docker的架构
docker包括三个基本概念:
镜像(Image):创建容器的模板
容器(Container):独立运行的一个或一组应用
仓库(Repository):保存镜像的仓库。docker Hub提供了庞大的镜像集合供使用(hub.docker.com)
私有仓库:用户可以在本地搭建私有docker仓库
2.3 一键安装docker
官方教程文档:
docker分为两个版本:docker CE
和docker EE
CE为社区免费版,EE为企业版,需付费。这里介绍的是CE的安装使用
2.3.1 官方一键安装脚本:
curl -fsSL https://get.docker.com | bash -s docker --mirror aliyun
2.3.2 国内一键安装脚本:
curl -sSL https://get.daocloud.io/docker | sh
若失效,使用以下一键安装脚本:
#!/bin/bash
read -p "安装(y/n):" judge_1
if [ $judge_1 = "y" ]; then
yum -y install yum-utils
if [ $? != 0 ]; then
echo "安装命令失败"
else
sudo yum install -y yum-utils
if [ $? != 0 ]; then
echo "安装工具包失败1.1"
else
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
if [ $? != 0 ]; then
echo "设置远程仓库失败1.2"
else
sudo yum install docker-ce
if [ $? != 0 ]; then
echo "安装失败1.3"
else
echo "安装完成"
fi
fi
fi
fi
else
echo "退出"
exit
fi
卸载安装docker
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl start docker
2.3.3 启动docker后台服务
sudo systemctl start docker
2.3.4 查看docker版本
docker version
2.4 镜像加速器
鉴于国内网络问题,后续从仓库拉取docker镜像会十分缓慢,此时需要配置加速器来解决
docker官方提供的中国registry mirror
阿里云加速器
DaoCloud加速器
2.4.1 官方加速器
配置加速器方法:
vi /etc/docker/daemon.json (若文件不存在请新建)
追加以下内容
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
重启docker使配置生效:
systemctl daemon-reload
systemctl restart docker
2.4.2 阿里云加速器
阿⾥云的镜像源有个加速器,可以加速你获取容器的速度。这个加速器地址是每个⼈专属的。 ⽹址: https://dev.aliyun.com/
登录阿里云个人账号–管理中心–容器镜像服务–镜像加速器
2.4.3 检查加速器是否生效
docker info
#当显示镜像地址后,则表示配置已生效。
三、镜像
镜像是docker的三大组件之一
docker运行容器需要本地存在对应的镜像。如果本地没有,则会从镜像仓库里下载
3.1 获取镜像
3.1.1 查找镜像
我们可以访问docker hub网站搜索镜像。
也可以通过命令搜索镜像。比如我们要搜索Tomcat的镜像:
docker search tomcat
3.1.2 下载镜像到本地
语法:
docker pull [选项] [仓库地址[:端口号]] 镜像名称[:版本号]
#如果不指定版本号,则默认拉取最新的版本
docker pull nginx
3.2 查看本地镜像
docker images
3.3 删除本地镜像
语法:
docker image rm [选项] <镜像1> <镜像2>
其中,<镜像>可以是镜像的长短ID,也可以是镜像名称或者镜像的摘要
docker image rm nginx
# 或者使用简写rmi
docker rmi nginx
3.4 保存镜像
3.4.1 镜像导出
如果大陆下载镜像太慢,可在能下载镜像的网络环境下载好,再将镜像保存到服务器,然后导入到国内服务器
docker save nginx -o nginx.tar
3.4.2 镜像导入
将已经下载好的本地镜像文件导入到docker
docker load -i nginx.tar
3.4.3 修改镜像名称
上图看到导入的镜像名字和标签都是,可以使用docker tag来修改镜像的名称和标签
docker tag (镜像ID) (镜像名称):(镜像标签)
docker tag c919045c4c2b nginx:test
四、容器
容器是独立运行的一个或一组应用,
镜像:定制的操作系统
容器:通过镜像创建好的虚拟机
4.1 容器常用命令
启动容器的方式有两种:
- 之前未创建容器,从镜像新建一个容器,并启动
- 之前创建过容器,但是是停止状态,现在要重新启动它
常用命令:查看正在运行的容器:docker ps 查看所有容器,包括停止的:docker ps -a 停止容器:docker stop (名称或ID) 停止所有容器:docker stop $(docker ps -a -q) 启动容器:docker start (名称或ID) 删除容器:docker rm (名称或id) (删前应先停止)
4.2 创建容器
语法:
docker run [参数] 镜像名称[:tag] [执行的命令]
常用参数:
-it:保持和docker容器内的交互,启动容器时,运行的任务结束后,使容器依然运行,不会退出(若不加-i,默认会停止容器)
-d: 后台运行容器
-p: 端口映射(宿主机的端口:容器的端口)
–rm: 容器在启动后,执行完命令或程序就销毁
–name: 给容器自定义名称
例如:
docker run -d –name web_nginx -p 80:8080 nginx
4.2 导出导入容器
如果要将服务器A的容器导入到服务器B运行
在服务器A导出镜像
docker save -o jira_image.tar haxqer/jira:9.17.4
在服务器A导出容器
docker export jira-srv -o jira-srv.tar
在服务器B导入镜像
docker load -i jira_image.tar
在服务器B导入容器
docker import jira-srv.tar <新镜像名称>
修改容器映射信息
修改容器的端口映射
# 停止要操作的容器
docker stop <容器ID>
# 修改容器配置文件
vim /var/lib/docker/containers/<容器ID>/hostconfig.json
# 重启docker
systemctl restart docker
# 启动容器
docker start <容器ID>
4.3 进入容器
当容器运行后,要怎么和容器内部操作容器呢?
docker exec -it (容器id或名字) bash
4.4 交换文件
可在宿主机和容器间相互拷贝文件
# 把容器的文件拷贝到宿主机
docker cp [option] 容器路径 本地路径
# 把宿主机文件拷贝到容器
docker cp [option] 本地路径 容器路径
# 举例:将宿主机的文件拷贝到容器
docker cp test.txt nginx_81:/usr/local/src/
4.5 查看容器日志
docker提供查看容器日志的命令:docker logs
docker logs --tail[=数量] [-f] 容器名
--tail=100:查看最后100条日志
--since:输出指定日期之后的日志
-f:查看实时日志
-t:查看日志产生的日期
例如:
docker logs --tail=10 -f nginx_81
五、数据卷(volume)
5.1 什么是数据卷
数据卷相当于软连接,将宿主机的目录软连接到容器里,这样只要修改了宿主机指定目录内的数据,容器映射的目录也会同步更新。不需要将数据复制到容器内部。
特性:
数据卷可以在容器之间共享和重用
对数据卷的修改会立即生效
对数据卷的更新不会影响镜像
数据卷的数据默认会一直存在,即使容器被删除
5.2 数据卷的操作
注:以下方式用得少,参照5.3的应用,可以直接指定数据卷的路径
#创建数据卷,默认数据会放到/var/lib/docker/volume/数据卷名称/_data目录下:
docker volume create 数据卷名称
#查看全部数据卷
docker volume ls
#查看指定数据卷
docker volume inspect 数据卷名称
#删除数据卷
docker volume rm 数据卷名称
5.3 数据卷的应用
将数据卷应用到容器,使容器能读取数据卷内的数据。
# 映射数据卷到容器(若数据卷不存在,会自动创建)
docker run -v 数据卷名称:容器内路径 镜像ID
# ※※※※直接指定一个路径作为数据卷的存储位置
docker run -v 路径:容器内路径 镜像ID
实例:
#从镜像新建一个容器,指定数据卷路径
docker run -it -d --name "nginx-81" -p 81:80 -v /data/volume/v1:/usr/share/nginx/html nginx
已经创建好的容器,怎么查看其映射了哪些目录呢?
docker inspect <容器id>
六、综合案例
6.1 创建Nginx集群
6.1.1 环境搭建
#拉取Nginx镜像
docker pull nginx
#查看镜像是否下载完成
docker images
#创建nginx容器,拷贝默认配置。(因为待会映射数据卷后,容器里默认的配置会被删)
docker run -it --name "nginx-test" -d
#进容器确认要拷贝的文件的路径
docker exec -it nginx-test bash
#拷贝配置文件到宿主机
docker cp nginx-test:/etc/nginx/nginx.conf /data/volume/v1/nginx/
docker cp nginx-test:/etc/nginx/conf.d/ /data/volume/v1/nginx/
#删除该临时容器
docker stop nginx-test
docker rm nginx-test
6.1.2 创建接入层nginx
通过前端接入层,分发流量到指定后端机器
#创建nginx接入层容器,并映射数据卷
touch /data/volume/v1/nginx/conf.d/access.conf
docker run -it --name "nginx-80" -d -p 80:80 -v /data/volume/v1/nginx/conf.d/access.conf:/etc/nginx/conf.d/access.conf nginx
6.1.3 创建后端容器
docker run -it -d --name "nginx-81" -p 81:80 -v /data/volume/v1/nginx/conf.d/:/etc/nginx/conf.d/ -v /data/volume/v1/nginx/html/:/usr/share/nginx/html/ nginx
docker run -it -d --name "nginx-82" -p 82:80 -v /data/volume/v1/nginx/conf.d/:/etc/nginx/conf.d/ -v /data/volume/v1/nginx/html/:/usr/share/nginx/html/ nginx
docker run -it -d --name "nginx-83" -p 83:80 -v /data/volume/v1/nginx/conf.d/:/etc/nginx/conf.d/ -v /data/volume/v1/nginx/html/:/usr/share/nginx/html/ nginx
6.1.4 修改接入层配置
修改接入层配置,利用upstream将访问的流量指向后端机器
vim /data/volume/v1/nginx/conf.d/access.conf
upstream myweb{
server 192.168.1.190:81;
server 192.168.1.190:82;
server 192.168.1.190:83;
}
server {
listen 80;
server_name localhost 192.168.1.190;
location / {
proxy_pass http://myweb;
}
}
6.1.5 部署网站数据
将网站页面放入宿主机的html目录(因为已经做了数据卷映射,宿主机的html目录和后端容器的html一致)
cp -r xxx /data/volume/v1/nginx/html/
6.1.6 重启接入层
可以进容器重启nginx服务,也可以直接重启容器
docker restart nginx-80
查看是否成功启动
docker ps
若未启动成功,查看日志错误原因
docker logs nginx-80
6.1.7 部署完成
访问80端口测试
6.2 创建mysql
6.2.1 创建镜像
#拉取镜像
docker pull mysql:5.6
#通过镜像创建容器,配置密码
docker run -it -d --name "mysql-5.6" -p 3306:3306 -e MYSQL_ROOT_PASSWORD='asdf5321' mysql:5.6
6.2.2 配置
MySQL默认只允许root用户本地登录,如果要在奇台机器上连接MySQL,必须手动授权
docker exec -it mysql-5.6 bash
mysql -uroot -p
#授权远程登录MySQL
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'asdf5321' WITH GRANT OPTION;
#这句话的意思是:赋予所有权限给'root'这个用户(也可以是其他用户比如'zhangsan'),在 '%'这台主机(%表示任何主机,也可以改为具体的192.168.1.20这个主机)上使用"asdf5321"这个密码登陆数据库;
FLUSH PRIVILEGES;
#删除远程访问权限
DELETE FROM mysql.user WHERE User="root" and Host="%";
开启防火墙的3306端口访问权限
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload
此时访问宿主机的3306端口来访问创建的MySQL容器了
七、定制镜像
如果镜像仓库里的镜像不能满足自己的需要,或者想自定义镜像时
7.1 Dockerfile常用命令
镜像实际就是定制每一层所添加的配置、文件。把每一层修改、安装、构建的命令都写入脚本,通过这个脚本来构建、定制镜像。这个脚本就是dockerfile
dockerfile是一个文本文件,期内包含了一条条指令,每条指令构建一层,描述该层如何构建。
FROM : 指定基础镜像
基础镜像不存在时会在docker hub上拉取
FROM <镜像>[:tag]
LABEL : 作者信息
LABEL maintainer="作者信息"
LABEL "com.example.vendor"="ACME Incorporated"
LABEL version="1.0"
LABEL description="这是备注"
ENV : 环境变量
ENV指令可以为docker容器设置环境变量,可以使用dokcer inspect来查看,也可以使用docker run --env <key>=<value>
来修改环境变量。
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME JAVA_HOME/jre
ENV CLASSPATHJAVA_HOME/lib/:JRE_HOME/lib/
ENV PATHPATH:$JAVA_HOME/bin/
USER : 切换用户身份
docker默认使用root。若不需要,建议切换使用者身份,因为root权限太大了有安全风险
WORKDIR : 切换工作目录
默认工作目录是/,只有RUN能执行cd命令切换目录。如果想让其他指令在指定目录下执行,就得依靠WORKDIR。WORKDIR动作的目录改变是持久的,不用每个指定都要运行一次WORKDIR。
VOLUME : 创建数据卷
创建一个可以从本地主机或其他容器挂载的挂载点。一般用来存放数据库和需要保持的数据等。
COPY : 复制文件到镜像
把宿主机的文件复制到镜像中
ADD : 复制文件到镜像
ADD和COPY类似,但是ADD的源可以是文件或目录,也可以是一个远程url,目的是目标容器的绝对路径。
EXPOSE : 打开镜像端口
打开容器要监听的端口,实现与外部通信
EXPOSE 80/tcp 23/udp
#不加协议 默认是tcp
RUN : 执行命令
RUN就像shell一样可以执行命令
RUN <命令>
RUN ["可执行文件", "参数1", "参数2"]
RUN wget www.sxxx.com/test.tar
7.2 Dockerfile案例
需求:创建一个镜像(基于Tomcat)里面要有index.html文件,写入hello world
7.2.1 创建dockerfile文件
mkdir -p /data/docker/domo1
cd /data/docker/domo1
vim Dockerfile
Dockerfile内容如下:
FROM tomcat:latest
RUN mkdir -p /usr/local/tomcat/webapps/ROOT/
RUN echo "hello world" >> /usr/local/tomcat/webapps/ROOT/index.html
WORKDIR /usr/local/tomcat/webapps/
7.2.2 构建镜像
基于Dockerfile来构建镜像
#参数-t表示指定镜像名,.表示Dockerfile文件的路径
docker build -t demo1 .
这样就可以构建一个名为demo1的自定义的镜像了
7.2.3 测试镜像
以该镜像创建一个容器,如果访问该Tomcat显示hello world则表示成功!
这样,通过该镜像创建出的容器都会包含自定义的这个html文件了
7.2.4 虚悬镜像
如果有两个同名和同标签的镜像,则老镜像的名字和标签都会显示<none>
,这就是虚悬镜像。一般来说这种镜像失去了存在的价值,可以随意删除。使用以下命令删除:
docker image prune
注:若虚悬镜像被容器使用,需要先删除容器才能删除虚悬镜像。
八、docker部署springboot项目
准备一个springboot jar项目
8.1 编写Dockerfile文件
FROM java:8
VOLUME /tmp
ADD xxxx.jar demo.jar
EXPOSE 5320
ENTRYPOINT: ["java","-jar","demo.jar"]
# FROM:导入基础镜像
# VOLUME /tmp : 因为Springboot的Tomcat默认使用/tmp作为工作目录,所以持久化/tmp目录作为springboot的工作目录
# ADD:将这个jar包复制并重命名到项目里
# EXPOSE: 默认端口
# ENTRYPOINT:容器启动时第一个运行的命令及其参数
8.2 编译镜像:
docker build -t test .
编译后,即生成一个该项目的镜像。
8.3 生成容器
docker run -d --name "test" -p 8080:5320 test
这样项目就在容器内运行了。将这个镜像拷贝到其他服务器上运行,实现项目的负载均衡
8.4 IDEA操作docker
上面已经实现项目容器化运行了,但是可以通过IDEA编辑器直接操作docker而不用通过命令行吗?
8.4.1 docker开启远程访问
#修改docker文件
vim /lib/systemd/system/docker.service
注释默认的`ExecStart`行,添加
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
# 重启服务
systemctl daemon-reload
systemctl restart docker
# 检测是否可以远程访问
curl http://127.0.0.1:2375/info
8.4.2 IDEA软件安装docker插件
在IDEA编辑器的插件里安装docker插件,重启IDEA使插件生效。
重启后在设置里找到docker插件进行配置,配置docker服务器的地址
这样就可以通过IDEA工具操作Linux服务器了
8.5 持续发布
如果这个项目需要持续版本迭代,要每次都编写Dockerfile文件生成镜像和生成容器吗?
传统的方式发布项目,需要通过打包、部署等操作手工发布。
而在持续集成过程中,项目一般使用Maven
编译打包,然后生成镜像,通过镜像上线能够大大提高上线效率,同时可以动态扩容和回滚。docker-maven-plugin
插件可以实现这个功能
。通过简单的配置,自动将镜像推送到仓库中。
8.5.1 配置插件
将以下代码复制到springboot项目的pom.xml
文件中,以自动打包成镜像,生成容器等操作:
<properties>
<docker.image.prefix>boxbull</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<!-- 镜像名称 boxbull/exam-->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--指定标签-->
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!-- 基础镜像jdk 1.8-->
<baseImage>java</baseImage>
<!-- 制作者提供本人信息 -->
<maintainer>boxbull</maintainer>
<!--切换到/ROOT目录 -->
<workdir>/ROOT</workdir>
<cmd>["java", "-version"]</cmd>
<entryPoint>["java", "-jar", "${project.build.finalName}.jar"</entryPoint>
<!--指定远程 docker api地址-->
<dockerHost>http://192.168.20.135:2375</dockerHost>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<!--用于指定需要复制的根目录,${project.build.directory}表示target目录-->
<directory>${project.build.directory}</directory>
<!--用于指定需要复制的文件。${project.build.finalName}.jar指的是打包后的jar 包文件。-->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
上面的docker-maven
插件插件实际上会将自动生成一个如下的Dockerfile文件:
FROM java
MAINTAINER boxbull
WORKDIR /ROOT
ADD /ROOT/boxbull-0.0.1-SNAPSHOT.jar /ROOT/
ENTRYPOINT ["java", "-jar", "boxbull-0.0.1-SNAPSHOT.jar"]
CMD ["java", "-version"]
8.5.2 项目打包发布
在项目的根目录执行:
mvn clean package docker:build
执行完成后即在服务器上生成了镜像、创建容器并更新项目版本
8.6 IDEA整合dockerCA加密认证
前面提到的配置是允许所有人都可以访问的,因为docker默认是root权限的,把2375端口暴露在外面,意味着别人随时都可以提取到你服务器的root权限,是很容易被黑客黑,因此,docker官方推荐使用加密的tcp连接,以Https的方式与客户端建立连接
(*步骤略)
九、docker图形化工具
docker图形页面管理工具常用的有三种,DockerUI
,Portainer
,Shipyard
。
DockerUI
是 Portainer
的前身,这三个工具通过docker api来获取管理的资源信息。以Portainer
最为受欢迎。
这里介绍Portainer
的安装使用
9.1 镜像获取
docker search portainer
docker pull portainer/portainer
9.2 启动容器
docker run -d --name portainer -p 8000:8000 -p 9000:9000 -v /data/docker/portainer:/data/portainer/portainer portainer/portainer
9.3 访问
浏览器访问ip:9000
评论(0)