微服务第四章-Docker部署

初识Docker

什么是Docker

每个应用都需要有自己的依赖和函数库,不同环境可能会有问题 

隔离容器=沙箱,防止不同依赖形成干扰从而隔离起来

打包应用时 是基于某个操作系统打包的,比如基于ubuntu打包的,那能在mac上运行吗?

 

所有的linux内核操作系统都可以分成两级 

一层是共享的内核-linux内核,不管是ubuntu还是centOS,区别是上层的系统应用不同

内核:是负责与计算机硬件交互的 比如说调用内存、cpu、读取文件等。内核把这些事情变成一个一个的指令,调用这些指令就可以操作计算机硬件了,但是这些指令比较简陋,如果基于指令去开发应用就太麻烦了。所以就有了系统应用

系统应用:比如说ubuntu,它会将内核的指令进行了组装再封装,形成了函数,许多的函数形成了函数库,程序员可以基于函数库进行开发。程序调用函数库,函数库调用内核指令,指令操作硬件,从而实现开发

问题来了:ubuntu的系统应用为什么不能在centOs系统上运行呢?

虽然内核一样,但是系统应用不同,也就是函数库不同,ubuntu上有的函数库centOS不一定有,或者名字不一样,比如一个ubuntu系统上的mysql应用迁移到了centOS系统上尝试去执行,可能会发现当mysql去调用一个函数库的时候,centOS上根本没有,那肯定就会报错了。这就是我们的应用 为什么不能跨系统的原因

针对这样的问题,我们的Docker干了什么事呢?

既然每个应用都依赖于系统函数库,那就把系统函数库和应用一起打包就好了,随便放到一个linux操作系统上,只要内核是linux内核,比如mysql迁移到了centOS系统上,它在执行的时候,调用的函数库是已经打包好了的函数库。而这个函数库直接调用操作系统的内核,而内核直接访问计算机硬件,这个调用就完成了,它不需要管系统应用是什么,基于这种模式,Docker就解决了跨系统问题

我们可以认为Docker打包好的程序包,可以运行在任何的linux内核的操作系统上

总结: 

Docker和虚拟机的区别

我们在windows系统上装centOS系统,怎么实现在一个系统装了另一个系统的呢?

其实是用到了一种Hypervisor技术,这种技术可以模拟出一个计算机的各种硬件,比如cpu内存等,然后在这个模拟出的计算机上 就可以安装任何我们想要的操作系统,比如centOS ,操作系统都可以安装,那么在它上边就可以安装适合的依赖、函数库、以及应用,这样就实现了跨系统的应用部署了。当应用在执行时,它会以为它在一台真实的电脑上

而docker它的应用在执行时,是直接调用操作系统内核的。所以执行性能要好很多

docker应用只是简单的封装了一些函数库、依赖(只是应用执行所必须的),占用体积小,最小的docker容器可能只有几兆,大的也就几十几百M

启动时:

  • 虚拟机得先启动虚拟的操作系统,而后再去启动虚拟操作系统上的应用。速度慢
  • docker是直接启动应用,就是说在一个操作系统上直接启动了一个进程

总结

Docker架构

镜像:函数库、依赖等打包,这些东西落到硬盘上就是一个一个的文件 。也可以说镜像就是硬盘中的文件(有日志文件,写数据的data文件,依赖文件等)

容器:可以理解为我们把mysql跑起来,其中的进程就是容器 ,只不过在docker里边容器还需要做隔离,里边会有独立的cpu资源,内存资源 ,甚至还有独立的文件系统。因此在该容器内运行的进程 它就会以为自己是这台计算机里的唯一进程了,从而起到了一种隔离的效果。

将来mysql镜像不管是启动一个容器还是多个容器,他们之间都是相互隔离的,当容器运行过程中必然会做数据读写操作  ,比如mysql将来会做数据存储工作,那么他们能不能把数据写到mysql镜像的的data目录里呢?显然是不能的,如果这么做了就相当于对镜像产生污染了

所以说镜像都是只读的,容器在运行的过程中,不能往镜像里写数据。可以基于镜像去创建容器,容器可以从镜像里读取数据

将来mysql容器写到哪里呢?很简单,从镜像中拷贝一份文件到自己的独立文件系统中,这就是隔离的一个特性了,在写数据的时候写到自己的空间的文件里 ,不会对别的容器产生影响,也不会对镜像产生影响,包括将来记录日志也是个写个的。将来我们基于镜像创建容器也是全新的,里边不会有任何污染

这样我们的镜像才会放心大胆的交给别人去使用 ,那么问题来了,我们怎么把镜像共享给别人去使用呢?

DockerHub:镜像托管,这样的平台称为镜像服务器

类似于git Hub,这个是做代码的托管

程序员可以用docker命令去完成镜像的构建,构建出mysql等各种各样的镜像,而后把这镜像上传到DockerHub服务器上去

那么我们该怎么样利用Docker去完成镜像的构建,或者是从远端拉取镜像呢?又该怎么样去运行容器呢

我们可以在本地自己构建镜像build,也可以远程去服务器上拉取镜像pull

然后就可以运行镜像创建容器了,守护进程也会帮我们创建容器

只有一些我们自己的微服务等才需要自己去构建,否则没必要

 一般情况下,我们就是向DockerServer发送命令,拉取镜像,启动镜像从而创建容器完成部署 

 

安装Docker,我这里是mac安装了,就不安装如下的了

注意:\ 斜杠是命令的拼接,命令太长,一行写不下,告诉系统我这个命令没结束,要往下接着读 

-y 就是安装的过程中不要问,问就是一路往下走

 查看docker版本

Docker的基本操作

镜像操作

获取镜像的两种方式docker build本地,和dockerpull 远程 

images在这里翻译成镜像

获取镜像一般有两种方法

1、本地获取,需要一个Dockerfile的文件,执行build命令,把Dockerfile构建成一个镜像

2、从服务器拉取镜像

查看本地有哪些镜像:docker images

删除本地镜像:docker rmi。 rmi全拼是remove images

镜像分享给别人

1、docker push 推送到服务器

2、将镜像拷贝给别人,执行docker save命令将镜像打成压缩包,别人执行docker load命令加载就可以了

查看docker所有命令:

docker --help :查看所有的命令

docker images --help :查看某个详细的命令

 案例:

Docker  dockerHub的网站,直接可以去搜索镜像名字

这个意思是官方镜像 

 点开后发现有很多版本

往上发现已经给了一个默认的拉取命令,没有指定版本,默认是最新的

 mac 先启动小鲸鱼,然后终端就可以执行docker pull nginx了,得先起来

 

 latest 就是最新版本

案例二:IMAGE是镜像的名称和版本号

发现导出成功了 

docker rmi 加镜像的名字或者id删除镜像

然后给别人进行安装 -i输入一个文件

 

查看打包的文件

删除镜像,可以用镜像名称,也可以用镜像id,版本号最新的就用latest

容器操作

容器相关命令

docker run 创建容器,还可以让容器处于运行状态

容器除了有运行,还会有暂停、停止状态

从运行到暂停命令:docker pause、

从暂停到运行命令:docker unpause

从运行到停止命令:docker stop

从停止到运行命令:docker start

暂停和停止的差别主要在于操作系统的处理方式,如果进入暂停状态,操作系统会将容器的进程挂起,容器关联的内存暂存起来了,cpu不再执行该进程,如果恢复了,那么内存空间恢复,程序接着运行

停止意味着不玩了,直接把进程杀死,内存被回收,保留的紧紧是文件,start会创建一个全新的进程

如何查看容器状态?ps 、logs日志

docker exec 可以操作容器内部

docker rm 删除容器,进程、内存回收,文件都会被删除,删除了个干干静静

案例:

进入官网,找到nginx往下拉,找一个最简单的运行命令

$ docker run --name some-nginx -d -p 8080:80 some-content-nginx

 注意:容器是对外隔离的,任何一台服务器想要访问我的容器,那么请走开,我不让你访问,而我们创建容器的目的就是为了让别人访问呀 所以做一个端口映射

比方说我们的宿主机有自己的很多端口,其中一个端口是80,那么我让宿主机的80和容器的80产生一个关联映射。这样一来,任何进入宿主机80的这个请求,就都会被转发到该容器的80端口去执行,这样就等于是nginx处理了这个请求

所以客户想要访问nginx容器,只需要去访问这台服务器,请求进来以后,宿主机一看端口,哦,往nginx容器里走呀,统一都扔过去,于是容器就处理了

所以端口映射的作用是:把本来完全隔离的容器 ,暴露一个小窗口,让你来透过它来访问!

宿主机端口可变,容器端口不可变,比如我想让宿主机的8080和容器的80端口映射,这样的话用户在访问的时候,就是访问8080,而不是80了

-p:端口映射

-d:后台运行,不加就是前台运行,比如360杀毒软件,我们点了小红x发现并没有关掉,它切换成后台了,我们打开任务管理器发现进程还在,这就是后台运行,点x直接关闭就是前台运行

最后一个参数是镜像名称,我们创建容器是基于那个镜像创建的呢,这里是nginx镜像,没有写标签tag,其实也就是最新版本的意思啦

启动容器保持后台运行 :基于nginx最新版本的镜像创建一个容器,起个名字,端口映射是 ,保持后台持续运行;返回的字符串是容器的唯一id

created 创建时间

status 运行状态,up正在运行

端口:宿主机端口与nginx端口的映射 

names: 容器的名称
 

创建后需要访问呀,访问宿主机看下,因为在我自己的本机上,这就说明容器部署成了

 如果关闭容器,docker pause id,那么在访问localhost就发现打不开了

查看日志,docker logs 容器名字,日志持续输出的话加个-f 

总结:

注意:-p是非常重要的,暴露一个端口,让外界可以访问

Docker容器的基本操作二

bash:像cd、vim、rm等都是bash命令 

 docker exec -it mr bash 进入容器

 pwd命令:显示当前的目录的路径

docker容器有自己的文件系统

我们要想知道比如nginx在docker 的安装位置,只能去找作者,就是docker,登陆docker网站,这里就有一个简单的静态内容地址

进入 cd  /usr/share/nginx/html

查看文件内容,用cat命令,cat index.html,

想要编写,vim 发现找不到命令,那是因为容器封装的函数nginx不需要vim命令,没有封装 ,再次证明文件系统和函数库都是阉割版的 

可以用代替的方式 

 从容器中退出来用exit命令

docker ps -a 展示所有容器,包括停掉的容器

删除容器,强制删除,不管容器是否在运行

总结:

不推荐修改:

1、不方便,命令没有

2、进入容器内修改是没有记录的 ,改完后可能忘了就,在启动一个容器修改成一模一样的,可能吗?自己都忘了呢

持久化启动,也去官网上找命令

如何访问呢?打开一个客户端RDM

然后进入exec容器内部,执行redis-cli启动redis客户端

打开客户端发现已经存储了

我们可以先进入bash 然后再进入cli,也可以直接进入cli

docker exec -it mr redis-cli ;因为docker exec -it mr是进入容器mr,然后执行一个命令,执行什么命令呢?执行redis-cli命令;而且退出只需要一次推出就可以了

数据卷(容器数据管理)

容器与数据耦合的问题:直接操作内容修改难

比如说有一个docker主机,在这个主机上会去管理很多很多的 数据卷,所有的数据卷一定会指向宿主机文件系统上的一个目录

数据卷目录只是一个虚拟的,在docker主机上创建了一个html文件,那么宿主机上一定就会创建一个html文件,他们俩会有一个映射关系

将来有一个容器,创建后比如说nginx,他的配置文件,页面等都在容器里,这就会造成容器与数据耦合了

我们让nginx的内部目录与数据卷进行关联,本质就是在和宿主机文件系统上的目录进行关联,此时docker就会管理该容器了 

比如说我们在nginx容器的文件里写点东西,这些东西会立即写到宿主机文件系统里,反之亦然,在宿主机文件系统里写数据,也会反馈到容器文件里

也就是说我们对宿主机文件的任意修改,会立刻反应到与之数据卷关联的容器内部,不用进入容器内去修改了

1、解决了修改难,2、修改后配置共享 让该容器也去挂载同一个数据卷,3、管理版本,将来容器删了,但是数据卷不会删

操作 :第一个是现实数据卷的所有信息,包括地址等

 挂载数据卷

-v 挂在数据卷,数据卷的名称:/容器内的数据卷地址 ,可以去dockrHub上看

案例:

如下操作我们发现docker的数据卷挂载目录不存在,可以路径是有的 

  

 mac下直接查看dockr地址是查不到的,因为还有一层vm,执行下边的命令,然后ls就可以看见了

docker run -it --privileged --pid=host justincormack/nsenter1

可以发现容器的目录

/usr/share/nginx/html

已经挂在到宿主机的真实目录下了

/var/lib/docker/volumes/html/_data

容器内的文件跑到容器外边来了

直接利用vi命令就可以修改了 

修改后,可以去容器内部查看是否修改

docker exec -it mn bash, 然后执行cat命令,发现已经更改了,访问localhost发现已经变了

那么问题来了,如果数据卷不存在那么启动容器直接挂载,数据卷还会创建成功嘛?

我们吧html数据卷删掉,mn容器删掉

docker rm mn ,然后是数据卷docker volume prune 就会把没有用的数据卷删掉,因为mn容器已经被删了,html就没人用了

 docker run --name mn -v html:/usr/share/nginx/html -d -p 80:80 nginx

我们发现数据卷被自动创建了 

打开浏览器刷新,发现已经恢复了 

这说明了我们启动容器在做数据卷挂在时,数据卷不存在,我们的docker会帮我们自动去创建

总结:所以大多数情况下我们不用自己去创建数据卷,可以由docker自动完成

以上演示是将数据卷挂在到容器目录!

 案例:将宿主机目录直接挂在到容器

 将tar文件拷贝到我的根目录下

创建目录 -p 是多级创建

mkdir -p mysql/data

然后找到命令-e 是指环境变量 MYSQL_ROOT_PASSWORD=my-secret-pw这环境变量密码是这个,还缺少端口和数据卷的挂载;conf.d d是指一个目录,my.cnf我们不建议直接覆盖这个目录,有很多自己的默认配置的,我们可以在另一个目录conf.d这个目录下操作,都会被加载

配置目录: 

数据存储目录:

docker run \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3339:3306 \
-v /Users/yuhaiyang/dockerMysqlConfigData/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
-v /Users/yuhaiyang/dockerMysqlConfigData/mysql/data:/var/lib/mysql \
-d \
mysql

 docker ps 发现容器已经存在了

 但是mac启动是失败的,没有起来,我也不知道为啥??? 版本问题,换个版本就可以了,但是还有一个问题就是我这里宿主机文件挂载后没有数据,不知道为啥

Dockerfile自定义镜像

镜像结构

从基础开始,逐层构建,依赖,打包,运行等,先从最底层构建

dockerfile语法

dockerfile就相当于是镜像构建的说明书

# 指定基础镜像 可以是一个从0开始的操作系统,也可以是别人共享的镜像
FROM ubuntu:16.04

 案例:

# dockerfile文件内容
# 指定基础镜像 可以是一个从0开始的操作系统,也可以是别人共享的镜像
FROM ubuntu:16.04
# 配置env环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝jdk和java项目的包 到/usr/local目录下
COPY ./jdk8.tar.gz $JAVA_DIR/

# 安装JDK tar -xf是解压缩,mv是重命名
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


# 以上的动作都是在安装JDK

COPY ./docker-demo.jar /tmp/app.jar

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar

-t全拼是-tag就是版本的意思(项目名称版本)

.代表的是dockerfile所在的目录 

 回车后就会逐步执行dockerfile的指令了,然后查看镜像就会发现已经构建好了,运行就和之前的一样了 

 访问发现已经成功了

 重复构建的话就太麻烦了

我们可以把jdk的构建先构建一个镜像 事实上已经有人帮我们做了

java:8-alpine

# dockerfile文件内容
# 指定基础镜像
FROM java:8-alpine

COPY ./docker-demo.jar /tmp/app.jar

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar

覆盖原来的文件,再次构建,发现又构建成功了

# 空格.
docker build -t javaweb:2.0 .

构建Java项目

Docker-Compos

实际项目中可能有成百上千个微服务,不可能都要我们手动去打包形成镜像

初识:是一个分布式应用部署的帮手 ,但是它要做部署,还需要compos文件才可以

以前使用docker run来运行一个容器,而现在是compos是用来运行多个容器,可以认为compos是多个docker run的集合

mysql一般不需要暴露接口,因为是给集群内用的,不用暴露

默认就是-d

mysql 、web 就是名字 --name的名字,指定镜像构建,和自己build 临时构建一个服务并运行

安装docker compos,mac的docker已经有docker compos功能了

修改文件权限加x是代表执行权,绿了就代表可以执行了 

 配置docker-compos的自动补全功能,方便

curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /usr/local/bin/docker-compose

报错的话修改host文件

199.232.68.133 raw.githubusercontent.com

 总结:就是基于compos文件帮助我们快速部署集群服务

部署微服务集群

将来我们把项目的jar包打好,然后放到相应的目录里 ,将来我们的docker-compose就会帮助我们自动的去构建微这几个微服务的镜像了,这些微服务依赖于mysql,mysql里面有数据库表等文件

docker-compose文件 

version: "3.2" #是版本号 这里用3.x的版本

services:
  nacos: #是服务名,所哟肚饿服务都需要注册到nacos里
    image: nacos/nacos-server
    environment: #就是单机启动的意思 -m参数 standalone
      MODE: standalone
    ports:
      - "8848:8848"
  mysql:
    image: mysql:5.7.25
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - "$PWD/mysql/data:/var/lib/mysql" #$pwd 就是当前目录,相对于dockercompos的当前目录
      - "$PWD/mysql/conf:/etc/mysql/conf.d/"
  userservice: #.就是当前目录 执行dockercompose当前目录下的Dockerfile
    build: ./user-service
  orderservice:
    build: ./order-service #执行当前目录下的Dockerfile
  gateway:
    build: ./gateway #执行当前目录下的Dockerfile
    ports:
      - "10010:10010" #我们网关才是整个微服务的入口,别的都不需要暴露

以前的地址都是localhost本地,现在是集群部署了,像mysql,order-service不一定在同一台机器了,那么如何知道他们的地址呢?

利用docker-compose部署时,所有的服务之间,都可以用服务名来访问,服务名mysql、orderservic、gateway等,这事compose底层做的一些配置

将原来的本机地址都改成服务名称 

下一步开始打包app.jar

我们可以看userservice的pom文件 有个build,这个就是做项目打包,finalName就是打包的名称

 然后我们利用生命周期,先clean,然后打包,打包成功后,服务会出现target目录

这里边就会出现app.jar的包

将我们项目的文件app.jar拷贝到dockerfile的同级目录下 

 以上所有准备就都做好了,只要我们去执行docker-compose镜像就回构建出,容器就会部署了

将其上传到服务器,然后就可以启动部署了

up:创建并执行容器

stop:停止 容器,down不仅回停掉,还会删掉

restart:重启

logs:查看日志

加-d就是后台运行 

 启动过程中发现orderservice、userservice报错了,是因为nacos还没起来,阿里巴巴的一个小bug,nacos起来后再重启一夏userservice、gateway等

Docker镜像服务

docker私有镜像仓库

dockerHub是公共的镜像仓库

docker Registry :docker注册中心,就是把我们的镜像注册到Registy的服务上去

搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。

官网地址:Docker

3.1.简化版镜像仓库

Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。

搭建方式比较简单,命令如下:

docker run -d \
    --restart=always \
    --name registry	\
    -p 5000:5000 \
    -v registry-data:/var/lib/registry \
    registry

命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。

访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像

3.2.带有图形化界面版本

因为不是官方的,使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:

dockerCompse里多个服务访问用服务名 这样ui控制台就知道了regisry的地址了,将来我们访问8080就可以了 

version: '3.0'
services:
  registry:
    image: registry
    volumes:
      - ./registry-data:/var/lib/registry
  ui:
    image: joxit/docker-registry-ui:static
    ports:
      - 8080:80
    environment:
      - REGISTRY_TITLE=私有仓库
      - REGISTRY_URL=http://registry:5000 #服务名称,就上边的同名:端口
    depends_on:#依赖于上边配置registry
      - registry

3.3.配置Docker信任地址

我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:

# 打开要修改的文件
vi /etc/docker/daemon.json
# 添加内容:
"insecure-registries":["http://192.168.150.101:8080"]
# 重加载
systemctl daemon-reload
# 重启docker
systemctl restart docker

新建一个文件夹,在创建一个yml文件,将内容拷贝里边去 

 访问就可以了 

向镜像仓库推送镜像

推送要重新起名字tag,要想推送到私有仓库,一定要重命名

执行推送后就成功了

从镜像仓库拉取镜像

 执行docker pull 名字 ,就拉取成功了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值