1.初识Docker
1.1 Docker简介
1.1.1 应用部署遇到的环境问题
- 大型项目组件多,运行环境复杂,部署时容易出现兼容性问题;
- 开发、测试和生产环境有所不同。
1.1.2 Docker解决依赖兼容问题
- Docker解决依赖的兼容问题:
- 将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包;
- 将每个应用放到一个隔离容器去运行,避免互相干扰。
1.1.3 Docker解决操作系统环境差异
- 操作系统结构:
- 计算机硬件:例如CPU、内存、磁盘等;
- 系统内核:所有Linux发行版的内核都是Linux,例如CentOS、Ubuntu、Fedora等。内核可以与计算机硬件交互,对外提供内核指令,用于操作计算机硬件;
- 系统应用:操作系统本身提供的应用、函数库。这些函数库是对内核指令的封装,使用更加方便。
- 应用(用户程序,非系统应用)与计算机交互的流程:
- 1)应用调用操作系统应用(函数库),实现各种功能;
- 2)系统函数库是对内核指令集的封装,会调用内核指令;
- 3)内核指令操作计算机硬件。
- Ubuntu和CentOSpringBoot都是基于Linux内核,无非是系统应用不同,提供的函数库有差异,如果将一个Ubuntu版本的MySQL应用安装到CentOS系统,MySQL在调用Ubuntu函数库时,会发现找不到或者不匹配,就会报错了:
- Docker解决不同系统环境的问题:
- Docker将用户程序与所需要调用的系统(比如Ubuntu)函数库一起打包;
- Docker运行到不同操作系统时,直接基于打包的函数库,借助于操作系统的Linux内核来运行。
1.1.4 小结
1.2 Docker和虚拟机的区别
- docker是一个系统进程;虚拟机是在操作系统中的操作系统;
- docker体积小、启动速度快、性能好;虚拟机体积大、启动速度慢、性能一般。
1.3 Docker架构
1.3.1 镜像和容器
- 镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像;
- 容器(Container):镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器进程做隔离,对外不可见。
- 镜像,就是把一个应用在硬盘上的文件、及其运行环境、部分系统函数库文件一起打包形成的文件包,这个文件包是只读的;容器,就是将这些文件中编写的程序、函数加载到内存中运行,形成进程,只不过要隔离起来。因此一个镜像可以启动多次,形成多个容器进程。
1.3.2 DockerHub
- DockerHub是一个官方的Docker镜像的托管平台。这样的平台称为DockerRegistry。
- 国内也有类似于DockerHub 的公开服务,比如 网易云镜像服务、阿里云镜像库等。
1.3.3 Docker架构
- Docker,一个CS架构的程序,由两部分组成:
- 服务端(server):Docker守护进程,负责处理Docker指令,管理镜像、容器等;
- 客户端(client):通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令;
1.3.4 小结
1.4 安装Docker
1.4.1 卸载(可选):
如果之前安装过旧版本的Docker,可以使用下面命令卸载:
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
1.4.2 安装docker
首先要虚拟机联网,安装yum工具
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2 --skip-broken
然后更新本地镜像源:
# 设置docker镜像源
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
yum makecache fast
然后输入命令:
yum install -y docker-ce
按照步骤安装,如果最后一步出错去对应阿里云镜像网址查看提示的版本是否正常下载有问题,自己在直接yum安装的时候遇到了对应最新版本文件为空(文件大小为0)安装出错的问题,解决方式是手动下载前一个版本上传的虚拟机中,然后手动安装。
1.4.3 启动docker
Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此直接关闭防火墙:
# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld
通过命令启动docker:
systemctl start docker # 启动docker服务
systemctl stop docker # 停止docker服务
systemctl restart docker # 重启docker服务
然后输入命令,可以查看docker版本:
docker -v
1.4.4 配置镜像加速
docker官方镜像仓库网速较差,我们需要设置国内镜像服务,参考 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
:
针对Docker客户端版本大于 1.10.0 的用户
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://tc6uil3n.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2.Docker的基本操作
2.1 镜像操作
2.1.1 镜像名称
- 镜名称一般分两部分组成:[repository]:[tag];
- 在没有指定tag时,默认是 latest ,代表最新版本的镜像;
2.1.2 镜像命令
2.1.3 案例-拉取、查看镜像
1)镜像仓库搜索nginx镜像,比如DockerHub:
2)根据查看到的镜像名称,拉取自己需要的镜像,通过命令:docker pull nginx
3)通过命令:docker images 查看拉取到的镜像
2.1.4 案例-保存、导入镜像
需求:利用docker save将nginx镜像导出磁盘,然后再通过load加载回来
1)查看命令的用法:docker xx --help
:
2) docker save 导出镜像:
- 命令格式:
docker save -o nginx.tar nginx:latest
- 运行结果:
3)docker load 加载镜像: - 先删除本地的 nginx镜像:
docker rmi nginx:latest
- load 命令加载本地文件:
docker load -i nginx.tar
- 运行结果:
2.1.5 练习拉取Redis镜像
2.2 容器操作
2.2.1 容器相关命令
- 容器的三个状态:
- 运行:进程正常运行
- 暂停:进程暂停,CPU不再运行,并不释放内存
- 停止:进程终止,回收进程占用的内存、CPU等资源
- 容器命令:
docker run
:创建并运行一个容器,处于运行状态;docker pause
:让一个运行的容器暂停;docker unpause
:让一个容器从暂停状态恢复运行;docker stop
:停止一个运行的容器;docker start
:让一个停止的容器再次运行;docker rm
:删除一个容器;注意删除一个容器必须先停止。
2.2.2 案例-创建并运行一个容器
- 创建并运行容器:
docker run --name containerName -p 80:80 -d nginx
- 命令解读:
docker run
:创建并运行一个容器;--name
:给容器起名字,如mn;-p
:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口;默认情况下,容器是隔离环境,将容器的80与宿主机的80关联起来,当我们访问宿主机的80端口时,就会被映射到容器的80,这样就能访问到nginx了-d
:后台运行容器;- nginx:镜像名称。
2.2.3 案例-进入容器,修改文件
该步骤修改容器内的文件比较繁琐,后续用数据卷实现比较方便。
步骤:
1)进入容器。进入我们刚刚创建的nginx容器的命令为:docker exec -it mn bash
命令解读:
docker exec
:进入容器内部,执行一个命令;-it
:给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互;- mn:要进入容器的名称;
- bash:进入容器后执行的命令,bash 是一个linux终端交互命令;
2)容器内部模拟一个独立的Linux文件系统:
3)查看 DockerHub 网站中的 nginx 页面,知道 nginx 的 html 目录位置在 /usr/share/nginx/html
,进入该目录:cd /usr/share/nginx/html
,查看目录下的文件:
4)修改 index.html 的内容:
容器内没有vi命令,无法直接修改,用下面的命令来修改:
sed -i -e 's#Welcome to nginx#传智教育欢迎您#g' -e 's#<head>#<head><meta charset="utf-8">#g' index.html
访问自己的虚拟机地址可看到结果:
2.2.4 小结
docker run
命令的常见参数--name
:指定容器名称;-p
:指定端口映射;-d
:让容器后台运行;
- 查看容器日志命令:
docker logs
;- 添加
-f
参数可以持续查看日志;
- 查看容器的状态:
docker ps
;docker ps -a
查看所有容器,包含已stop的。
2.3 数据卷(容器数据管理)
2.3.1 数据卷
**数据卷(volume)**是一个虚拟目录,指向宿主机文件系统中的某个目录。
作用:将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全。
完成数据卷挂载,对容器的一切操作都会作用在数据卷对应的宿主机目录。
2.3.2 数据卷操作命令
- 基本语法:
docker volume [COMMAND]
; docker volume
命令是数据卷操作,根据命令后跟随的command来确定下一步的操作:create
创建一个volume;inspect
显示一个或多个volume的信息;ls
列出所有的volume;prune
删除未使用的volume;rm
删除一个或多个指定的volume。
2.3.3 创建和查看数据卷
1)创建数据卷:docker volume create html
;
2)查看所有数据卷:docker volume ls
;
3)查看数据卷详细信息卷:docker volume inspect html
;
可以得到创建的 html 数据卷观澜的宿主机目录:/var/lib/docker/volumes/html/_data
;
2.3.4 挂载数据卷
创建容器时,通过 -v 参数挂在一个数据卷到某个容器内的目录:
docker run --name containerName -v html : /root/html -p 8080:80 nginx
其中 -v html : /root/html
表示把 html 数据卷挂载到容器内的 /root/html 目录。
2.3.5 案例-给nginx挂载数据卷
1)创建容器并挂载数据卷到容器内的 html 目录:
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
2)进入 html 数据卷所在位置,修改html内容(在虚拟机中,可以通过 vi 修改文件,也可以借助 FinalShell 直接双击修改):
# 查看html数据卷的位置
docker volume inspect html
# 进入该目录
cd /var/lib/docker/volumes/html/_data
# 修改文件
vi index.html
2.3.6 案例-给MySQL挂载本地目录
- 容器不仅仅可以挂载数据卷,也可以直接挂载到宿主机目录上,即也可以直接挂载到目录:
- 带数据卷模式:宿主机目录 --> 数据卷 —> 容器内目录;
- 直接挂载模式:宿主机目录 —> 容器内目录
- 目录挂载与数据卷挂载的语法:
- -v [宿主机目录]:[容器内目录];
- -v [宿主机文件]:[容器内文件]。
2.3.7 小结
- docker run的命令中通过 -v 参数可以挂载文件或目录到容器中:
- 数据卷挂载:-v volume名称:容器内目录;
- 目录挂载:
- -v 宿主机文件:容器内文件;
- -v 宿主机目录:容器内目录
- 数据卷挂载与目录直接挂载的区别:
- 数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找;
- 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看。
3.Dockerfile自定义镜像
3.1 镜像结构
- 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。
- MySQL镜像结构:
- 镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。构建镜像就是实现上述打包的过程。
3.2 Dockerfile语法
- Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
3.3 构建Java项目
3.3.1.基于Ubuntu构建Java项目
- 基于Ubuntu镜像构建一个新镜像,运行一个java项目:
- 步骤1:在linux系统上新建一个空文件夹docker-demo
- 步骤2:拷贝资料中的 docker-demo.jar、jdk8.tar.gz、Dockerfile 文件到 docker-demo 目录(可以直接借助FinalShell拖动上传),Dockerfile 内容放于本节末尾;
- 步骤3:进入docker-demo,运行命令
docker build -t javaweb:1.0 .
(一定要注意末尾的点不要漏掉,不然会报错),创建镜像,此时可以通过docker images
查看镜像;
- 步骤4:创建容器并运行
docker run --name web -p 8090:8090 -d javaweb:1.0
; - 步骤5:访问 http://虚拟机ip:8090/hello/count;
- Dockerfile 内容:
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
3.3.2.基于java8构建Java项目
- 上述基于Ubuntu基础镜像,添加任意自己需要的安装包,构建镜像比较麻烦,有些多次构建时重复性的工作;所以大多数情况下,我们都可以在一些安装了部分软件的基础镜像上做改造——构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。
- 基于java:8-alpine镜像,将一个Java项目构建为镜像:
- 步骤1:新建一个空的目录 docker-demo-from-java8apline ,然后在目录中新建一个文件,命名为Dockerfile,编写内容(放于末尾,可以借助 FinalShell 直接双击进行编辑);
- 步骤2:拷贝资料提供的docker-demo.jar到这个目录中并重命名为 app.jar;
- 步骤3:编写Dockerfile文件:
- a )基于java:8-alpine作为基础镜像
- b )将app.jar拷贝到镜像中
- c )暴露端口
- d )编写入口ENTRYPOINT
- 步骤4:使用docker build命令构建镜像 `` ;
- 步骤5:使用docker run创建容器并运行(注意因为同样使用了8090端口,可以将前面创建的java容器停止并删除);
- Dockerfile文件内容:
FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
EXPOSE 8090
ENTRYPOINT java -jar /tmp/app.jar
3.4. 小结
-
- Dockerfile的本质是一个文件,通过指令描述镜像的构建过程
-
- Dockerfile的第一行必须是FROM,从一个基础镜像来构建
-
- 基础镜像可以是基本操作系统,如Ubuntu。也可以是其他人制作好的镜像,例如:java:8-alpine
4.Docker-Compose
- Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器.
4.1.初识DockerCompose
Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。格式如下:
version: "3.8"
services:
mysql:
image: mysql:5.7.25
environment:
MYSQL_ROOT_PASSWORD: 123
volumes:
- "/tmp/mysql/data:/var/lib/mysql"
- "/tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf"
web:
build: .
ports:
- "8090:8090"
DockerCompose文件可以看做是将多个docker run命令写到一个文件,只是语法稍有差异。
4.2.安装DockerCompose
1.下载
# 安装
curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
2.修改文件权限
# 修改权限
chmod +x /usr/local/bin/docker-compose
3.Base自动补全命令
# 补全命令
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
如果这里出现错误,需要修改自己的hosts文件:
echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts
4.3.部署微服务集群
- compose 文件:包含5个service服务,注意修改mysql登陆密码为自己实际的密码;
- 修改微服务配置:微服务部署为容器后,通过容器名互相访问,因此将order-service、user-service、gateway服务的mysql、nacos地址都修改为基于容器名的访问;
- 打包:Dockerfile中的jar包名称都是app.jar,因此我们的每个微服务都需要用这个名称,通过修改pom.xml中的打包名称来实现;
- 拷贝jar包到部署目录;
- 部署:将文件整个cloud-demo文件夹上传到虚拟机中,进入目录,执行命令
docker-compose up -d
; - 查看日志
docker compose logs -f
,发现 SpringBoot 项目报错,发现是 nacos 启动过慢,执行docker-compose restart gateway userservice orderservice
重启三个service,访问结果如下:
5.Docker镜像仓库
搭建私有镜像仓库。