一、为什么要学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 CEdocker 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图形页面管理工具常用的有三种,DockerUIPortainerShipyard

DockerUIPortainer 的前身,这三个工具通过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

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。