在之前的nginx案例中,修改nginx的html页面时,需要进入nginx内部。并且因为没有编辑器,修改文件也很麻烦。
这就是因为容器与数据(容器内文件)耦合带来的后果。
要解决这个问题,必须将数据与容器解耦,这就要用到数据卷了。
2.3.1.什么是数据卷**数据卷(volume)**是一个虚拟目录,指向宿主机文件系统中的某个目录。
一旦完成数据卷挂载,对容器的一切 *** 作都会作用在数据卷对应的宿主机目录了。
这样,我们 *** 作宿主机的/var/lib/docker/volumes/html目录,就等于 *** 作容器内的/usr/share/nginx/html目录了
2.3.2.数据集 *** 作命令数据卷 *** 作的基本语法如下:
docker volume [COMMAND]
docker volume命令是数据卷 *** 作,根据命令后跟随的command来确定下一步的 *** 作:
- create 创建一个volume
- inspect 显示一个或多个volume的信息
- ls 列出所有的volume
- prune 删除未使用的volume
- rm 删除一个或多个指定的volume
需求:创建一个数据卷,并查看数据卷在宿主机的目录位置
① 创建数据卷
docker volume create html
② 查看所有数据
docker volume ls
结果:
③ 查看数据卷详细信息卷
docker volume inspect html
结果:
可以看到,我们创建的html这个数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data目录。
小结:
数据卷的作用:
- 将容器与数据分离,解耦合,方便 *** 作容器内数据,保证数据安全
数据卷 *** 作:
- docker volume create:创建数据卷
- docker volume ls:查看所有数据卷
- docker volume inspect:查看数据卷详细信息,包括关联的宿主机目录位置
- docker volume rm:删除指定数据卷
- docker volume prune:删除所有未使用的数据卷
我们在创建容器时,可以通过 -v 参数来挂载一个数据卷到某个容器内目录,命令格式如下:
docker run --name mn -v html:/root/html -p 8080:80 nginx
这里的-v就是挂载数据卷的命令:
- -v html:/root/htm :把html数据卷挂载到容器内的/root/html这个目录中
需求:创建一个nginx容器,修改容器内的html目录内的index.html内容
分析:上个案例中,我们进入nginx容器内部,已经知道nginx的html目录所在位置/usr/share/nginx/html ,我们需要把这个目录挂载到html这个数据卷上,方便 *** 作其中的内容。
提示:运行容器时使用 -v 参数挂载数据卷
步骤:
① 创建容器并挂载数据卷到容器内的HTML目录
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
② 进入html数据卷所在位置,并修改HTML内容
# 查看html数据卷的位置 docker volume inspect html # 进入该目录 cd /var/lib/docker/volumes/html/_data # 修改文件 vi index.html2.3.6.案例-给MySQL挂载本地目录
容器不仅仅可以挂载数据卷,也可以直接挂载到宿主机目录上。关联关系如下:
- 带数据卷模式:宿主机目录 --> 数据卷 —> 容器内目录
- 直接挂载模式:宿主机目录 —> 容器内目录
如图:
语法:
目录挂载与数据卷挂载的语法是类似的:
- -v [宿主机目录]:[容器内目录]
- -v [宿主机文件]:[容器内文件]
需求:创建并运行一个MySQL容器,将宿主机目录直接挂载到容器
实现思路如下:
1)在将课前资料中的mysql.tar文件上传到虚拟机,通过load命令加载为镜像
2)创建目录/tmp/mysql/data
3)创建目录/tmp/mysql/conf,将课前资料提供的hmy.cnf文件上传到/tmp/mysql/conf
4)去DockerHub查阅资料,创建并运行MySQL容器,要求:
① 挂载/tmp/mysql/data到mysql容器内数据存储目录
② 挂载/tmp/mysql/conf/hmy.cnf到mysql8容器的配置文件
③ 设置MySQL密码
docker run -d --name mysql-test01 -p 3306:3306 --privileged=true -v /tmp/mysql/data:/var/lib/mysql -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.252.3.7.小结
docker run的命令中通过 -v 参数挂载文件或目录到容器中:
- -v volume名称:容器内目录
- -v 宿主机文件:容器内文
- -v 宿主机目录:容器内目录
数据卷挂载与目录直接挂载的
- 数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找
- 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看
常见的镜像在DockerHub就能找到,但是我们自己写的项目就必须自己构建镜像了。
而要自定义镜像,就必须先了解镜像的结构才行。
3.1.镜像结构镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。
我们以MySQL为例,来看看镜像的组成结构:
简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。
我们要构建镜像,其实就是实现上述打包的过程。
3.2.Dockerfile语法构建自定义的镜像时,并不需要一个个文件去拷贝,打包。
我们只需要告诉Docker,我们的镜像的组成,需要哪些baseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来Docker会帮助我们构建镜像。
而描述上述信息的文件就是Dockerfile文件。
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么 *** 作来构建镜像。每一个指令都会形成一层Layer。
更新详细语法说明,请参考官网文档: https://docs.docker.com/engine/reference/builder
3.3.构建Java项目 3.3.1.基于Ubuntu构建Java项目需求:基于Ubuntu镜像构建一个新镜像,运行一个java项目
-
步骤1:新建一个空文件夹docker-demo
-
步骤2:拷贝课前资料中的docker-demo.jar文件到docker-demo这个目录
-
步骤3:拷贝课前资料中的jdk8.tar.gz文件到docker-demo这个目录
-
步骤4:拷贝课前资料提供的Dockerfile到docker-demo这个目录
其中的内容如下:
# 指定基础镜像 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
-
步骤5:进入docker-demo
将准备好的docker-demo上传到虚拟机任意目录,然后进入docker-demo目录下
-
步骤6:运行命令:
docker build -t javaweb:1.0 .
-
步骤7:运行镜像
docker run --name javaweb1 -p 8090:8090 -d javaweb:1.0
最后访问 http://192.168.150.101:8090/hello/count,其中的ip改成你的虚拟机ip
3.3.2.基于java8构建Java项目虽然我们可以基于Ubuntu基础镜像,添加任意自己需要的安装包,构建镜像,但是却比较麻烦。所以大多数情况下,我们都可以在一些安装了部分软件的基础镜像上做改造。
例如,构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。
需求:基于java:8-alpine镜像,将一个Java项目构建为镜像
实现思路如下:
-
① 新建一个空的目录,然后在目录中新建一个文件,命名为Dockerfile
-
② 拷贝课前资料提供的docker-demo.jar到这个目录中
-
③ 编写Dockerfile文件:
-
a )基于java:8-alpine作为基础镜像
-
b )将app.jar拷贝到镜像中
-
c )暴露端口
-
d )编写入口ENTRYPOINT
内容如下:
FROM java:8-alpine COPY ./docker-demo.jar /tmp/app.jar EXPOSE 8090 ENTRYPOINT java -jar /tmp/app.jar
-
-
④ 使用docker build命令构建镜像docker build -t javaweb:2.0 .
-
⑤ 使用docker run创建容器并运行docker run --name javaweb2 -p 8091:8090 -d javaweb:2.0
小结:
-
Dockerfile的本质是一个文件,通过指令描述镜像的构建过程
-
Dockerfile的第一行必须是FROM,从一个基础镜像来构建
-
基础镜像可以是基本 *** 作系统,如Ubuntu。也可以是其他人制作好的镜像,例如:java:8-alpine
Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器!
4.1.初识DockerComposeCompose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。格式如下:
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"
上面的Compose文件就描述一个项目,其中包含两个容器:
- mysql:一个基于mysql:5.7.25镜像构建的容器,并且挂载了两个目录
- web:一个基于docker build临时构建的镜像容器,映射端口时8090
DockerCompose的详细语法参考官网:https://docs.docker.com/compose/compose-file/
其实DockerCompose文件可以看做是将多个docker run命令写到一个文件,只是语法稍有差异。
4.2.安装DockerCompose参考课前资料
4.3.部署微服务集群需求:将之前学习的cloud-demo微服务集群利用DockerCompose部署
实现思路:
① 查看课前资料提供的cloud-demo文件夹,里面已经编写好了jkl;’
'-compose文件
② 启动nacos微服务
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server:1.4.1
注意: nacos微服务启动之后一定要重启网关,否则在后续微服务会报错“failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried:”启动网关命令
systemctl restart firewalld.service
③ linux默认不给docker-compose挂载的数据卷读写的权限,需要关闭selinux,mysql的数据卷才可以挂载成功
vim /etc/sysconfig/selinux SELINUX=enforcing 改为 SELINUX=disabled 重启虚拟机
④ 通过docker inspect查看容器的ip,修改自己的cloud-demo项目,将子项目nacos地址改为容器ip
⑤ 使用maven打包工具,将项目中的每个微服务都打包为app.jar
⑥ 将打包好的app.jar拷贝到cloud-demo中的每一个对应的子目录中
⑦ 将cloud-demo上传至虚拟机,利用 docker-compose up -d 来部署
注意:
-
通过docker logs -f xxx及时查看日志信息
-
错误1:查看微服务报错failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried:
解决方案:先重启nacos,再重启防火墙systemctl restart firewalld.service,
-
错误2:查看mysql日志permission denied
原因分析:linux默认禁止docker-compose挂载数据卷,所以需要给予权限
解决方案:修改文件vim /etc/sysconfig/selinux,将SELINUX=enforcing 改为 SELINUX=disabled,重启虚拟机
-
错误3: Access denied for user 'root'@'172.17.0.3' (using password: YES)
解决方案:mysql密码错误,目前课前资料给的mysql密码设定的是123
-
错误4:Unable to start docker Container from docker-compose “unknown flag: iidfile”
解决方案:docker-compose版本太高了,需要降下来
百度网盘下载:https://pan.baidu.com/s/1cxuly3dRoZ8BgVklmxfriQ 密码:rcqi
查看课前资料提供的cloud-demo文件夹,里面已经编写好了docker-compose文件,而且每个微服务都准备了一个独立的目录:
内容如下:
version: "3.2" services: nacos: image: nacos/nacos-server environment: MODE: standalone ports: - "8848:8848" mysql: image: mysql:5.7.25 environment: MYSQL_ROOT_PASSWORD: 123 volumes: - "$PWD/mysql/data:/var/lib/mysql" - "$PWD/mysql/conf:/etc/mysql/conf.d/" userservice: build: ./user-service orderservice: build: ./order-service gateway: build: ./gateway ports: - "10010:10010"
可以看到,其中包含5个service服务:
- nacos:作为注册中心和配置中心
- image: nacos/nacos-server: 基于nacos/nacos-server镜像构建
- environment:环境变量
- MODE: standalone:单点模式启动
- ports:端口映射,这里暴露了8848端口
- mysql:数据库
- image: mysql:5.7.25:镜像版本是mysql:5.7.25
- environment:环境变量
- MYSQL_ROOT_PASSWORD: 123:设置数据库root账户的密码为123
- volumes:数据卷挂载,这里挂载了mysql的data、conf目录,其中有我提前准备好的数据
- userservice、orderservice、gateway:都是基于Dockerfile临时构建的
查看mysql目录,可以看到其中已经准备好了cloud_order、cloud_user表:
查看微服务目录,可以看到都包含Dockerfile文件:
内容如下:
FROM java:8-alpine COPY ./app.jar /tmp/app.jar ENTRYPOINT java -jar /tmp/app.jar4.3.2.修改微服务配置
因为微服务将来要部署为docker容器,而容器之间互联不是通过IP地址,而是通过容器名。这里我们将order-service、user-service、gateway服务的mysql、nacos地址都修改为基于容器名的访问。
如下所示:
spring: datasource: url: jdbc:mysql://mysql:3306/cloud_order?useSSL=false username: root password: 123 driver-class-name: com.mysql.jdbc.Driver application: name: orderservice cloud: nacos: server-addr: nacos:8848 # nacos服务地址4.3.3.打包
接下来需要将我们的每个微服务都打包。因为之前查看到Dockerfile中的jar包名称都是app.jar,因此我们的每个微服务都需要用这个名称。
可以通过修改pom.xml中的打包名称来实现,每个微服务都需要修改:
app org.springframework.boot spring-boot-maven-plugin
打包后:
4.3.4.拷贝jar包到部署目录编译打包好的app.jar文件,需要放到Dockerfile的同级目录中。注意:每个微服务的app.jar放到与服务名称对应的目录,别搞错了。
user-service:
order-service:
gateway:
4.3.5.部署最后,我们需要将文件整个cloud-demo文件夹上传到虚拟机中,理由DockerCompose部署。
上传到任意目录:
部署:
进入cloud-demo目录,然后运行下面的命令:
docker-compose up -d
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)