SpringCloud学习(八)——Docker

1. 认识Docker

1.1 容器

在了解Docker前,我们首先来认识什么是容器。

在典型的虚拟化环境中,一台或多台虚拟机运行在一个物理服务器之上,这些物理服务器又使用着像 Xen、Hyper-V 等管理程序。而容器运行在操作系统内核之上,我们可以将其称为操作系统级虚拟化。

在深入了解底层容器概念之前,我们需要了解两个关键的 Linux 概念:

  1. 用户空间:运行用户程序(应用程序、进程)所需的所有代码被称为用户空间。当启动程序操作时,例如创建一个文件,用户空间中的进程会向内核空间发出系统调用。
  2. 内核空间:这里有着与系统硬件、存储等交互的内核代码,是操作系统的核心。

从本质上讲,容器是一个进程。当我们启动一个应用程序,比如说 Nginx Web 服务器,这个时候实际上是在启动一个进程。而进程本身是一个具有有限隔离的自包含指令。

那么如果我们仅使用进程运行和操作所需的文件与配置来隔离进程,又会怎样呢?而这正是容器的工作原理。容器基本上是一个具有足够隔离用户空间组件的进程,因此它给人一种独立操作系统的感觉。

父容器进程可能有一个子进程,所以可以说,一个容器也是一组进程。

1.2 Linux容器

Linux 有两个重要的内核功能,分别是命名空间(namespaces)和控制组(control groups)。在主机中,容器与容器之间的隔离正是由这两个内核功能实现的。

命名空间为容器设置了边界,让容器拥有了自己的挂载点、用户、IP 地址、以及进程管理等。创建容器就是创建一个隔离良好的环境来运行服务(进程)。为了达到这种级别的隔离,容器应该要有自己的文件系统、IP 地址、挂载点、进程 ID 等,这就需要使用 Linux 命名空间来实现这一点。使用这些命名空间,容器可以拥有自己的网络接口、IP 地址等。每个容器都拥有自己的命名空间,并且在该命名空间内运行的进程在其他命名空间中没有任何权限。

Linux 控制组管理着容器使用的资源,我们可以限制容器的 CPU、内存、网络和 IO 资源。由于我们可以在主机内运行多个容器,因此应该有一种机制来限制资源的使用、设备的访问等。而这里正是控制组的用武之地。如果不限制,单个容器可能最终会占用所有的主机资源,无资源可用就会导致其他容器的崩溃。

1.3 Docker

Docker 是一个流行的用 Go 语言开发的开源项目,由 Dotcloud 公司开发。Docker 基本上就是一个容器引擎,它使用 Linux 内核功能(如命名空间和控制组)在操作系统之上创建容器。

除了作为一种容器技术之外,Docker 还具有定义明确的包装器组件,这使打包应用程序变得十分容易。要知道,在 Docker 出现之前,运行容器并不是一件容易的事。所有的这一切意味着,Docker 通过将所有应用程序系统的需求打包到容器中,完成了将应用程序与基础设施分离的所有工作。例如,如果有一个 Java jar 文件,我们可以在任何安装了 java 的服务器上运行它。同样的,一旦使用 Docker 将容器与所需的应用程序打包在一起,我们就可以在任何其他安装了 Docker 的主机上运行它。

2. 配置Docker

2.1 安装Docker

接下来我们就对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

docker-ce 为社区免费版本。稍等片刻,docker即可安装成功。

输入下面的命令测试Docker是否安装成功

docker -v

安装成功时会输出Docker 的版本号,如下
在这里插入图片描述

2.2 启动Docker

Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!

启动docker前,一定要关闭防火墙后!!

# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld

通过以下命令对Docker进行操控:

systemctl start docker  # 启动docker服务

systemctl stop docker  # 停止docker服务

systemctl restart docker  # 重启docker服务

2.3 配置镜像加速

docker官方镜像仓库网速较差,我们需要设置国内镜像服务,一般选择的是阿里云的镜像服务,配置时只需要将以下命令复制并执行即可:

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://debe2hlb.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

3. Docker镜像操作

首先来看下镜像的名称组成:

  • 镜名称一般分两部分组成:[repository]:[tag]。
  • 在没有指定tag时,默认是latest,代表最新版本的镜像

比如需要使用 Nginx 的镜像,那么使用1.9版本的 Nginx 命令为 nginx:1.9 ,直接输入 nginx 则默认为最新版本。

Docker镜像操作中常见的命令流程如下:
在这里插入图片描述
接下来我们以 Nginx镜像的操作为例。

3.1 拉取镜像

首先我们进入到镜像仓库搜索Nginx的镜像,这里可以使用镜像仓库DockHub ,然后搜索Nginx,复制其中的pull命令,界面如下,
在这里插入图片描述
直接复制pull命令,其后是没有tag的,即得到的是最新版的,如果需要指定版本,可以在下面的红框中进行寻找,并补在tag的位置。

我们需要先使用命令 systemctl start docker 将docker进行启动,然后将Nginx镜像使用命令 systemctl start docker 进行拉取,拉取成功后,可以使用 docker images 命令查看本地镜像,查看如下:

在这里插入图片描述

3.2 镜像的打包和加载

使用 save 命令可以将镜像打包成一个压缩文件,之后还可以使用 load 命令进行加载,这样更利于镜像存储和传递,比如我需要将Nginx镜像打包为nginx.tar,则使用一下命令,

docker save -o nginx.tar nginx:latest

使用 ll 查看当前路径下的文件后,显示有 nginx.tar 的存在,
在这里插入图片描述
然后我们将镜像进行删除,删除使用的命令是 docker rmi image 命令,这里删除Nginx镜像的命令如下:

docker rmi nginx:latest

再次使用 docker images 命令则查看不到任何镜像,
在这里插入图片描述
使用 load 命令可以将打包的镜像进行加载,这里我们加载打包的Nginx镜像为,

docker load -i nginx.tar

加载压缩包的镜像以及查看的命令如下,
在这里插入图片描述
可以看到,加载了压缩包的镜像后,Nginx镜像又出现在了本地仓库。

3.3 查看帮助文档

docker命令如果有不清楚的部分,一般都会使用帮助文档进行查询,比如使用 docker --help 则可以查看docker的全部命令,但这些命令都没有具体的参数,比如我想查看 save 命令的具体参数,那么直接使用 docker save --help 即可查看所有的参数,在实际中如果有命令不清楚的,一般都会使用 --help 进行查看。

4. 容器命令

docker最重要的就是容器,那么我们自然也就需要操作容器了,容器状态有以下的三种,
在这里插入图片描述
常用的跟容器相关的命令有以下几个:

# 进入容器执行命令
docker exec
# 查看容器运行日志
docker logs
# 查看所有的容器及运行状态
docker ps
# 删除指定容器
docker rm

4.1 运行容器

可以去镜像仓库DockHub 查看相应的容器的使用方法,以Nginx为例,其使用方法在页面上有如下内容,
在这里插入图片描述

比如,我们可以使用下面的命令来运行一个Nginx容器,

docker run --name containerName -p 80:80 -d nginx

上述命令中 docker run 是创建并运行一个容器, --name 参数是给容器起一个别名,-p 将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口。因为docker中的容器是隔离的,所以外部的访问不能直接访问到容器内部,使用该命令后,该容器会与宿主机的端口进行关联,在外部访问宿主机端口时,会将其命令映射到docker容器中进行访问。-d 参数表示是后台运行。

现在我们运行Nginx,如下,

docker run --name mn -p 80:80 -d nginx

使用 docker ps 查看运行状态如下:
在这里插入图片描述
运行后产生的一串编码是容器的唯一ID。

最后,访问虚拟机的IP地址的80端口可以看到Nginx已经启动,
在这里插入图片描述
使用 docker logs mn 还可以对指定的容器查看日志。

4.2 进入容器

以上面的Nginx容器为例,因为容器是隔离的,所以我们没有办法在外面操控容器的细节,这时我们就可以进入容器内部,使用如下命令进入到容器的内部,

docker exec -it mn bash

docker exec 进入容器内部,执行一个命令,-it 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互,mn 要进入的容器的名称,bash 进入容器后执行的命令,bash是一个linux终端交互命令。
在这里插入图片描述
输入的命令如以上图片所示。可见,当我们进入容器内部后,是进入的根目录,输入 ls ,下面有与Linux根目录类似的一个个文件夹,这也证明了容器内部是独立并且隔离的,输入 exit 即可退出容器。

exec 命令也可以进入容器内部对文件进行修改,但是这是不推荐的,一是容器内并没有 vi 命令,修改并不方便,二是因为容器内修改是没有记录的,无法追溯你的修改记录。

4.3 数据卷

当我们需要对容器内的文件进行修改时,需要进入到容器内部进行修改,极其不方便的同时,以后如果要升级容器必然删除旧容器,所有数据都跟着删除了,这个时候,就需要一种方式来解决这个问题,我们采用的方式就是数据卷。

数据卷(volume)是一个虚拟目录,指向宿主机文件系统中的某个目录,而之后在宿主机的目录下也会创建一个跟容器内目录相同的结构,修改数据卷关联的目录内文件的内容后,其会立即更改到容器中。

现在我们来以更改Nginx的欢迎界面的文字为例,将 “Welcome to nginx” 改为 “Welcome to ikun” 。

首秀安,我们创建一个数据卷,使用 docker volume create 命令进行创建,我们下面创建一个名为 html 的数据卷,

docker volume create html

使用 docker volume ls 可以查看创建的数据卷。

然后我们需要找到 “Welcome to nginx” 在哪个文件夹中,这需要查看Dockerhub里的说明,
在这里插入图片描述
从这里我们可以看出静态页面的地址,于是,在运行docker时我们可以将这个地址与数据卷进行关联,使用命令如下:

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

数据卷的操作主要有如下命令:

# 显示一个或多个volume的信息
docker volume inspect
# 删除未使用的volume
docker volume prune
# 删除一个或多个指定的volume
docker volume rm

使用 docker volume inspect html 可以看到数据卷的一些信息,
在这里插入图片描述
上面的 Mountpoint 就是数据卷挂载的地址 。

我们切换到上面的挂载地址所在的目录可以看到,目录下面有两个文件,这两个文件就是Nginx容器内部目录下的两个文件。
在这里插入图片描述
我们只需要对这两个文件进行修改,容器内的文件一样会进行修改,比如,我们修改 index.html 中的文件,将 “Welcome to nginx” 改为 “Welcome to ikun” ,保存后,访问网页,可以看到页面的欢迎内容已经被修改了。

在这里插入图片描述

这里我们是先创建的数据卷再进行的数据卷的映射,其实可以不用创建数据卷,直接映射,如果数据卷不存在,docker会为你自动创建一个数据卷。

5. 自定义镜像

镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。

我们以MySQL为例,来看看镜像的组成结构:

在这里插入图片描述

简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。我们要构建镜像,其实就是实现上述打包的过程。

5.1 Dockerfile语法

构建自定义的镜像时,并不需要一个个文件去拷贝,打包。我们只需要告诉Docker,我们的镜像的组成,需要哪些BaseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来Docker会帮助我们构建镜像。描述上述信息的文件就是Dockerfile文件。Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer,该文件需要我们自己去写,基本语法如下:

指令说明示例
FROM指定基础镜像FROM centos:7
ENV设置环境变量ENV key value
COPY拷贝本地文件到镜像的指定目录COPY ./mysql-5.7.rpm /tmp
RUN执行Linux的shell命令,一般是安装过程中的命令RUN yun install gcc
EXPOSE指定容器运行时监听的端口,给镜像使用者看EXPOSE 8080
ENTERPOINT镜像中应用的启动命令,容器运行时调用ENTERPOINT java -jar /tmp/app.jar

比如我们传入一个javaweb项目 docker-demo以及JDK8的包 jdk8.tar.gz ,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

之后再执行 docker build -t javaweb:1.0 .即可构建镜像,该条命令中的 . 指的是dockerfile所在的目录。

5.2 基于java8构建Java项目

虽然我们可以基于Ubuntu基础镜像,添加任意自己需要的安装包,构建镜像,但是却比较麻烦。所以大多数情况下,我们都可以在一些安装了部分软件的基础镜像上做改造。例如,构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。

java:8-alpine 正好提供了这样的基础镜像,我们构建镜像时就可以基于这个镜像包来构建,就不需要额外安装java8的安装包了,该方式的Dockerfile文件内容如下:

FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
EXPOSE 8090
ENTRYPOINT java -jar /tmp/app.jar

肉眼可见的少了很多的代码。

6. DockerCompose

Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。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"

上面的Compose文件就描述一个项目,其中包含两个容器:

  • mysql:一个基于mysql:5.7.25镜像构建的容器,并且挂载了两个目录
  • web:一个基于docker build临时构建的镜像容器,映射端口时8090

DockerCompose的详细语法参考官网:https://docs.docker.com/compose/compose-file/
其实DockerCompose文件可以看做是将多个docker run命令写到一个文件,只是语法稍有差异。

6.1 安装DockerCompose

首先下载DockerCompose文件到 /usr/local/bin/ 目录下,然后修改文件的权限,使用如下命令:

chmod +x /usr/local/bin/docker-compose

之后再配置自动补全命令。

配置自动补全的下载源在国外,这里建议修改一下hosts文件再配置,修改如下:

echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts

然后执行命令,配置自动补全:

curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

6.2 配置DockerCompose

将服务全部打包,点击IDEA上的 Package 按钮,能够将Module打包为一个 jar 文件,然后,在里面配置一个名为 docker-compose.yml 的文件,其中的语法是按照DockerCompose的语法来进行编写的,内容如下:

version: "3.2"

services:
  nacos:
    image: nacos/nacos-server
    environment:
      MODE: standalone
    ports:
      - "8848:8848"
  # 配置MySQL
  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"

之后,将文件夹与 docker-compose.yml 文件传送到虚拟机下,启动Docker,使用 docker-compose up -d 启动微服务,并且将其转为后台运行。

使用 docker-compose logs 能够查看打印的日志,如果不出意外的话,日志里面应该有报错的信息。因为Nacos的启动相比其他微服务的启动来说太慢了,这就导致了其他微服务启动后Nacos都还未启动,这种情况下我们需要在Nacos启动后,将其他微服务进行重启,重启如下

docker-compose restart gateway userservice orderservice

之后输入虚拟机的IP地址,并访问统一网关 http://192.168.59.233:10010/user/2?authorization=admin,能够打印出信息,这就大功告成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值