目录
引言
我们写的代码会接触到好几个环境:开发环境、测试环境以及生产环境:
开发人员在开发环境下写好了程序,就会打包成war包给测试人员进行测试,测试人员在测试环境下测试没问题后会给运维人员,运维人员将war包部署到生产环境上,能够成功允许则流程结束。
但是这个过程中往往会出现一些问题,比如开发环境上用的是JDK8的版本,但是测试环境上用的是JDK7的版本,这样代码就可能出一些问题,那么我们能不能将环境和代码一起打包测试呢?
答案当然是可以的,我们把环境和代码放在一个容器里面,把容器传给测试人员进行测试,这样就不会出现软件跨环境迁移的问题了。
而上面所说的容器就是我们今天要学习的Docker容器。
一、Docker概述
1.1Docker概念
Docker 是一个开源的应用容器引擎,诞生于 2013 年初,基于 Go 语言实现。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。
Docker 容器是完全使用沙箱机制,相互隔离,并且性能开销极低。
Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版)
Docker 是一种容器技术,解决了软件跨环境迁移的问题。
1.2安装Docker
Docker可以运行在MAC、Windows、CentOS、UBUNTU等操作系统上,本课程基于CentOS 7 安装Docker,官网:https://www.docker.com/。
前面一直踩坑花了好长时间(建议不要使用CentOS 7以下更低版本的系统,否则官网现在不提供支持了,安装Docker会很麻烦,后续可能CentOS7也不支持了,建议选新一点的版本)
我们使用SecureCRT连接虚拟机中的Linux系统,实现可见安装教程。
安装Docker主要用到以下几条命令:
# 1、yum 包更新到最新
yum update
# 2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
# 3、 设置yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 4、 安装docker,出现输入的界面都按 y
yum install -y docker-ce
# 5、 查看docker版本,验证是否验证成功
docker -v
输入docker -v验证,终于装好了docker。
1.3Docker架构
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。
1.4配置Docker镜像加速器
默认情况下,将来从docker hub(https://hub.docker.com/)上下载docker镜像,太慢。一般都会配置镜像加速器:
- USTC:中科大镜像加速器(https://docker.mirrors.ustc.edu.cn)
- 阿里云
- 网易云
- 腾讯云
我配置的是阿里云的镜像加速器,具体可见安装教程。
二、Docker命令
2.1Docker服务相关命令
启动docker服务:systemctl start docker
停止docker服务:systemctl stop docker
重启docker服务:systemctl restart docker
查看docker服务状态:systemctl status docker
设置开机启动docker服务:systemctl enable docker
我们首先测试一下启动服务命令,
然后停止服务,查看docker状态,
我们还可以重启docker服务,然后再查看docker状态,
我们还可以通过systemctl enable docker命令,设置docker服务为开机自启动。
2.2Docker镜像相关命令
2.2.1查看镜像
docker images
docker images –q # 查看所有镜像的id
我们输入docker images查看本地的镜像,因为我们还没有下载镜像,所以是空的,
2.2.2搜索镜像
docker search 镜像名称
我们可以在网络中搜索镜像,比如我们搜索redis的镜像,
可以看到网络上有很多redis的镜像信息,一般我们都下载official也就是官方维护的镜像
2.2.3拉取镜像
docker pull 镜像名称
然后我们使用docker pull的命令拉取redis镜像,
关于想要下载的镜像有哪些版本,我们可以上https://hub.docker.com/去查询,
我们现在下载一个5.0版本的redis镜像,
2.2.4删除镜像
docker rmi 镜像id # 删除指定本地镜像
docker rmi `docker images -q` # 删除所有本地镜像
我们现在删除最新版本的redis镜像,
2.3Docker容器相关命令
2.3.1创建容器
docker run 参数
参数说明:
- -i:保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
- -d:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。
- -it 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器
- --name:为创建的容器命名。
我们创建一个交互式容器,镜像使用cenots7,
我们还可以同样使用centos7镜像来创建守护式容器,在退出容器时不会关闭,
此时创建完成后没有自动进入容器,需要使用docker exec命令进入。
2.3.2查看容器状态
docker ps # 查看正在运行的容器
docker ps –a # 查看所有容器
因为上面我们创建的是交互式容器,所以需要加参数-a来查看所有容器,
可以看到c2容器还在运行,c1容器已经退出了。
2.3.3停止容器
docker stop 容器名称
此时c2容器还在运行,我们可以使用stop命令停止c2容器,
2.3.4启动容器
docker start 容器名称
我们还可以将刚刚停止的c2容器重新启动,
2.3.5删除容器
docker rm 容器名称
docker rm `docker ps -aq`#删除所有容器,`docker ps -aq`为查询所有容器id
假设我们现在不想要c1容器了,可以使用rm命令删除,
注意:如果容器是运行状态则删除失败,需要停止容器才能删除,
2.3.6查看容器信息
docker inspect 容器名称
这个命令是查看某个容器的具体详细信息,和查看状态不同,
三、Docker容器的数据卷
3.1数据卷的概念及作用
我们先思考这样几个问题,
1、Docker 容器删除后,在容器中产生的数据也会随之销毁吗?
答案是肯定的,当容器删除后,其内部产生的数据都会销毁。
2、Docker 容器和外部机器可以直接交换文件吗?
外部机器和容器是不能直接交换的,二者网络不互通,但是可以通过宿主机来交换文件。
3、容器之间想要进行数据交互?
这里就要引出数据卷的概念了,
- 数据卷是宿主机中的一个目录或文件
- 当容器目录和数据卷目录绑定后,对方的修改会立即同步
- 一个数据卷可以被多个容器同时挂载
- 一个容器也可以被挂载多个数据卷
数据卷主要作用有:
- 容器数据持久化
- 外部机器和容器间接通信
- 容器之间数据交换
3.2配置数据卷
docker run ... –v 宿主机目录(文件):容器内目录(文件) ...
我们在创建启动容器时,使用 –v 参数 设置数据卷,注意:
- 目录必须是绝对路径
- 如果目录不存在,会自动创建
- 可以挂载多个数据卷
我们使用 -v 参数在创建c1容器时设置数据卷,
我们还可以同时查看宿主机的root目录,发现也创建了对应的data目录,
此时我们进入数据卷目录,在宿主机的/root/data目录下创建一个tz.txt,
如果我们配置数据卷成功,那么c1容器的/root/data_container目录下面应该也会有tz.txt,
果然在data_container目录下有tz.txt文件,宿主机的修改立马同步到容器中了。
同样的,我们在docker容器中修改文件,也会同步到宿主机中,
然后我们在宿主机中查看,可以看到test.txt也出现了,
现在我们将c1容器删除,可以看到宿主机中的data目录还在,并未收到影响,
此时我们还可以再创建一个容器,用-v 命令将data目录的数据通过数据卷"恢复"到容器中,
这样就实现了数据的持久化,当容器销毁时,我们还可以恢复之前的数据。
同时我们还可以一个容器绑定多个目录,假设我们现在创建c2容器,挂载多个目录,
接下来我们测试一下两个容器之间的相互通信,我们新建一个c3容器,将宿主机的~/data目录绑定到c3容器的/root/data目录下,
我们再新建一个c4容器,同样挂载宿主机的~/data目录,
此时我们在c4容器内对data目录进行修改,新增一个chat.txt文件,
我们回到c3容器中进行查看,可以看到chat.txt文件同步过来了,
这样同一个数据卷绑定到不同的容器中,可以间接实现两个容器之间的数据交换。
3.3配置数据卷容器
如果要实现多容器进行数据交换,我们可以将多个容器挂载到同一个数据卷上(如果容器比较多则这种方法比较麻烦,需要对每个容器都挂载数据卷),还有另一种方法就是使用数据卷容器。
假设现在有两个容器c1、c2,他们想要进行数据交换,我们可以再创建一个数据卷容器c3,c3挂载到宿主机中的数据卷目录,然后c1、c2分别挂载到数据卷容器c3上,这样c1、c2、c3就都挂载到了宿主机的数据卷目录上,就可以实现数据交换。
下面我们来看一下具体如何配置数据卷容器,
1、创建启动c3数据卷容器,使用 -v 参数设置数据卷
docker run -it --name=c3 -v /volume centos:7 /bin/bash #后面的/bin/bash可以省略
这里的 -v /volume 指定的是容器中的目录, 没有指定对应宿主机的数据卷目录,但是docker会自动在宿主机上创建一个目录作为数据卷,所以也不会报错。
我们使用docker inspect c3来查看一下c3容器的详细信息,看到里面的Mounts属性:
这里的Source的值就是docker帮我们在宿主机上面创建的数据卷目录,而Destination则是我们使用-v参数在容器中创建的对应目录。
2、创建启动c1、c2容器,使用 --volumes-from 参数设置数据卷
docker run -it --name=c1 --volumes-from c3 centos:7 /bin/bash
docker run -it --name=c2 --volumes-from c3 centos:7 /bin/bash
这里的 --volumes-from c3 命令是将当前的容器挂载到c3数据卷容器对应的数据卷上,简单来说,执行了这两条命令之后,c1、c2、c3都挂载到了同一个数据卷上
3、我们在数据卷容器c3中的volume文件夹新建一个test.txt,
然后我们在c1、c2容器的volume 目录中查看文件,
在宿主机的数据卷目录下,也会产生相应的test.txt文件,所以此时即使把c3数据卷容器删除也不会丢失数据。
四、Docker应用部署
接下来我们学习一下如何在Docker中部署一些常用的软件。
4.1MySQL部署
需求:在Docker容器中部署MySQL,并通过外部mysql客户端操作MySQL Server
主要实现步骤如下:
- 搜索mysql镜像
- 拉取mysql镜像
- 创建容器
- 操作容器中的mysql
但是有个很大的问题,外部机器无法直接操作宿主机容器中的MySQL Server,
因为容器内的网络服务和外部机器不能直接通信,但是外部机器和宿主机可以直接通信,而宿主机和容器又可以直接通信,所以当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射到宿主机的端口上。外部机器访问宿主机的该端口,从而间接访问容器的服务。
这种操作称为:端口映射。
接下来我们尝试一下在Docker上部署MySQL,
1、搜索mysql镜像
docker search mysql
2、拉取mysql镜像,我们下载5.6版本的mysql
docker pull mysql:5.6
3、创建容器,设置端口映射、目录映射
首先在/root目录下创建mysql目录,用于存储mysql数据信息,
mkdir ~/mysql
cd ~/mysql
创建好了之后我们开始创建容器,
docker run -id \
-p 3307:3306 \
--name=c_mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.6
参数说明:
- -p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口。(这里映射到3307端口是第一次学习好分辨,也可以直接映射到宿主机的3306端口,比较常规)
- -v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。配置目录
- -v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs。日志目录
- -v $PWD/data:/var/lib/mysql :将主机当前目录下的data目录挂载到容器的 /var/lib/mysql 。数据目录
- -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
进入mysql容器之后我们可以简单测试一下mysql的命令,查看一下数据库,
mysql -uroot -p密码 #登录mysql数据库,这里我们设置的密码是123456
show databases; #查看mysql本地有哪些数据库
至此容器中的mysql就可以正常使用了。那么如何在外部机器连接这个容器中的mysql呢?
首先我们打开本机的SQLyog,新建一个连接,
然后我们修改一下连接的配置,
然后就连接成功了,实现了外部机器连接虚拟机容器中的mysql。
4.2Tomcat部署
需求:在Docker容器中部署Tomcat,并通过外部机器访问Tomcat部署的项目
在容器中部署Tomcat服务器的步骤和mysql差不多,
1、搜索tomcat镜像
docker search tomcat
2、拉取tomcat镜像
docker pull tomcat
3、创建容器,设置端口映射、目录映射
首先我们还是在/root目录下创建tomcat目录,用于存储tomcat数据信息,
mkdir ~/tomcat
cd ~/tomcat
然后我们创建tomcat容器,
docker run -id --name=c_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
因为此时我们将webapps目录挂载到了宿主机的tomcat目录下,所以可以直接在tomcat目录下创建一个web工程,我们简单创建一个test目录,创建一个index.html资源以供访问,
在index.html中我们就写一个简单的一句话显示,保存退出,
然后我们在外部机器中访问容器中tomcat服务器的index.html资源,成功了!
所以后续我们可以直接将写好的项目扔到宿主机的~/tomcat目录就可以完成部署。
4.3Nginx部署
需求:在Docker容器中部署Nginx,并通过外部机器访问Nginx
1、搜索nginx镜像
docker search nginx
2、拉取nginx镜像
docker pull nginx
3、创建容器,设置端口映射、目录映射
首先我们还是在宿主机/root目录下创建nginx目录,用于存储nginx数据信息,
mkdir ~/nginx
cd ~/nginx
我们还需要在nginx目录下创建conf目录,并创建nginx.conf配置文件,
mkdir conf
cd conf
vim nginx.conf
配置的内容如下:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
配置好了保存,然后我们创建nginx容器,
docker run -id --name=c_nginx \
-p 80:80 \
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
参数说明:
- -p 80:80:将容器的 80端口映射到宿主机的 80 端口。
- -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:将主机当前目录下的 /conf/nginx.conf 挂载到容器的 :/etc/nginx/nginx.conf。配置目录
- -v $PWD/logs:/var/log/nginx:将主机当前目录下的 logs 目录挂载到容器的/var/log/nginx。日志目录
接着我们还需要在nginx/html目录中创建一个index.html以供访问,
在index.html中我们显示一句话hello nginx docker,
4、使用外部机器访问nginx
直接访问宿主机的ip地址即可,端口号默认就是80,
4.4Redis部署
需求:在Docker容器中部署Redis,并通过外部机器访问Redis
1、搜索Redis镜像
docker search redis
2、拉取redis镜像
这里我们选择下载5.0版本的redis,
docker pull redis:5.0
因为之前我们拉取过一遍了,所以这里提示不需要下载了。
3、创建容器,设置端口映射
docker run -id --name=c_redis -p 6379:6379 redis:5.0
这里我们直接创建容器,做了一个端口的映射,没有做目录的映射,
4、使用外部机器连接redis
redis-cli.exe -h 192.168.49.200 -p 6379
然后我们到windows系统的redis安装目录下,启动cmd命令进行测试,
如果一直闪退的话可能是:没有设置redis的最大内存,解决方法:
在redis的配置文件(redis.windows.conf)中加入maxmemory和maxheap配置
五、Dockerfile
Dockerfile是用于制作Docker镜像的,所以学习Dcokerfile之前我们先学习一下Docker镜像原理。
5.1Docker镜像原理
首先我们思考这样几个问题:
- Docker 镜像本质是什么?
- Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要好几个G?
- Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
一个操作系统一般是由以下几个部分组成的:进程调度子系统、进程通信子系统、内存管理子系统、设备管理子系统、文件管理子系统、网络通信子系统、作业控制子系统,
而Linux文件系统由bootfs和rootfs两部分组成,
- bootfs:包含bootloader(引导加载程序)和 kernel(内核)
- rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件
不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等。
而Docker镜像是由特殊的文件系统叠加而成,
- 最低端是bootfs,并且使用的是宿主机的bootfs,加载linux的内核
- 第二层是 root文件系统rootfs,称为base image
- 然后再往上可以叠加其他的镜像文件(例如jdk镜像、tomcat镜像等)
例如上图所示,tomcat镜像需要依赖jdk镜像,而jdk镜像又需要依赖rootfs基础镜像,所以在安装tomcat的时候,会一层一层的安装了以下所有的依赖镜像,但是对外只表现为tomcat镜像。这种技术我们称为统一文件系统技术。
统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。
一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。这些镜像我们一般都是只读的,如果用户想要对镜像进行修改,可以通过容器来实现。
当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器,这个容器又是一个独立的文件系统,用户可以进行自己的修改,也可以将自己修改后的容器重新生成新的镜像。
综上所述,Docker镜像的本质其实就是一个分层文件系统。
5.2Docker镜像制作
制作一个Docker镜像可以有两种方式,
5.2.1容器转换为镜像
之前我们学习到了用户可以在容器中进行修改,修改完成后用户可以将容器制作成新的镜像,提供给别人进行使用,转换的命令如下:
docker commit容器id 镜像名称:版本号
但是制作成镜像之后不能传输,我们还需要把镜像转成压缩文件方便传输,
docker save-o 压缩文件名称 镜像名称:版本号 #压缩镜像文件
docker load–i 压缩文件名称 #加载压缩文件,还原成镜像
我们之前在tomcat容器中写了一个index.html,
接下来我们试着将这个容器制作成镜像并压缩,首先将容器制作成镜像,
然后我们将这个镜像文件压缩一下,
接下来我们把本地的镜像删除,尝试通过tar包还原成镜像文件(模拟传输到别人电脑的过程),首先是删除本地的tz_tomcat镜像,
然后我们解压压缩包,
我们将该镜像重新生成容器,会发现在根目录中生成的tz.txt还在,但是目录挂载的test项目没有。
第一种方式把容器变为镜像的时候,非目录挂载的文件都可以放到镜像中,要想让目录挂载的文件也一起放到镜像中,我们一般会使用第二种方式。
5.2.2Dockerfile
Dockerfile是一个文本文件,包含了一条条的指令。
每条指令构建一层,基于基础镜像,最终构建出一个新的镜像。
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建新的镜像来测试
- 对于运维人员:在部署时,可以实现应用的无缝移植
文档的编写规范可以参考Docker Hub网址。
在dockerfile中的常用关键字及其意义如下:
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN ["command" , "param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD ["command" , "param1","param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value |
ARG | 构建参数 | 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME ["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。 |
SHELL | 指定执行脚本的shell | 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell |
5.3Dockerfile案例
上面我们简单熟悉了一下Dockerfile的关键字,现在我们通过几个案例熟悉一下Dockerfile的使用。
案例一:自定义centos7镜像,要求:
1、默认登录路径为/usr(官方的默认登录路径为/)
2、可以使用vim(官方的只能使用vi命令)
实现步骤如下:
- 定义父镜像:FROM centos:7
- 定义作者信息:MAINTAINER aoylaotang <csertangzhe@cug.edu.cn>
- 执行安装vim命令: RUN yum install -y vim
- 定义默认的工作目录:WORKDIR /usr
- 定义容器启动执行的命令:CMD /bin/bash
- 通过dockerfile构建镜像:docker bulid –f dockerfile文件路径 –t 镜像名称:版本
首先我们创建dockerfile文件,
然后我们开始编辑dockerfile文件,
编写好了之后保存退出,然后使用dockerfile文件创建镜像,
创建好镜像之后开始创建容器,
案例二:定义dockerfile,发布springboot项目
这里我们准备一个简单的springboot项目,通过网页localhost:8080/hello访问controller类的hello方法,在网页上输出"Hello, Spring Boot!"
首先我们要将这个springboot项目打包,
注意要在pom.xml文件中添加打包需要的组件,
<build>
<plugins>
<!-- 打jar包时如果不配置该插件,打出来的jar包没有清单文件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
然后到target目录去查找生成的jar包,
现在我们将这个jar包传输到虚拟机的linux系统中,在SecureCRT命令行窗口alt+p,使用put命令进行文件传输,将windows系统下的jar包传输到centos虚拟机的根目录中,
然后我们在根目录下查看,
我们将jar包移动到docker-files目录下,方便部署,
实现步骤如下:
- 定义父镜像:FROM java:8
- 定义作者信息:MAINTAINER aoylaotang <csertangzhe@cug.edu.cn>
- 将jar包添加到容器: ADD springboot.jar app.jar
- 定义容器启动执行的命令:CMD ["java","-jar","app.jar"]
- 通过dockerfile构建镜像:docker bulid –f dockerfile文件路径 –t 镜像名称:版本
我们首先编辑一个springboot_dockerfile,
编辑好了之后保存退出,使用build命令创建镜像,
然后我们通过镜像创建容器,
创建好了我们就可以直接在windows系统下通过宿主机的地址+9000端口+hello的路径访问,
六、Docker服务编排
6.1服务编排概述
微服务架构的应用系统中一般包含若干个微服务(比如网购双十一),每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,维护的工作量会很大。例如:
- 要从Dockerfile build image 或者去dockerhub拉取image
- 要创建多个container
- 要管理这些container(启动停止删除)
服务编排:按照一定的业务规则批量管理容器。
6.2Docker Compose
Docker Compose是一个编排多容器分布式部署的工具,
提供命令集管理容器化应用的完整开发周期,包括服务构建,启动和停止。
具体使用步骤如下:
- 利用 Dockerfile 定义运行环境镜像
- 使用 docker-compose.yml 定义组成应用的各服务
- 运行 docker-compose up 启动应用
6.2.1Docker Compose的安装
# Compose目前已经完全支持Linux、Mac OS和Windows,在我们安装Compose之前,需要先安装Docker。下面我们以编译好的二进制包方式安装在Linux系统中。
curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 设置文件可执行权限
chmod +x /usr/local/bin/docker-compose
# 查看版本信息
docker-compose -version
# 卸载docker-compose。因为是二进制包方式安装的,所以删除二进制文件即可
rm /usr/local/bin/docker-compose
6.2.2Docker Compose的使用
需求:使用docker compose编排nginx+springboot项目
1、创建docker-compose目录
mkdir ~/docker-compose
cd ~/docker-compose
2、编写 docker-compose.yml 文件
version: '3'
services:
nginx:
image: nginx
ports:
- 80:80
links:
- app
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
app:
image: helloapp
expose:
- "8080"
3、创建./nginx/conf.d目录
mkdir -p ./nginx/conf.d
4、在./nginx/conf.d目录下 编写aoylaotang.conf文件,通过访问nginx的80端口反向代理到http://app:8080的hello服务,
server {
listen 80;
access_log off;
location / {
proxy_pass http://app:8080;
}
}
5、在~/docker-compose 目录下 使用docker-compose 启动容器
docker-compose up
然后我们访问宿主机的80端口进行测试,
七、Docker私有仓库
Docker官方的Docker hub(https://hub.docker.com)是一个用于管理公共镜像的仓库,我们可以从上面拉取镜像 到本地,也可以把我们自己的镜像推送上去。
但是,有时候我们的服务器无法访问互联网,或者你不希望将自己的镜像放到公网当中,那么我们就需要搭建自己的私有仓库来存储和管理自己的镜像。
7.1搭建私有仓库
# 1、拉取私有仓库镜像
docker pull registry
# 2、启动私有仓库容器
docker run -id --name=registry -p 5000:5000 registry
# 3、打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog,看到{"repositories":[]} 表示私有仓库 搭建成功
# 4、修改daemon.json
vim /etc/docker/daemon.json
# 在上述文件中添加一个key,保存退出。此步用于让 docker 信任私有仓库地址;注意将私有仓库服务器ip修改为自己私有仓库服务器真实ip
{"insecure-registries":["私有仓库服务器ip:5000"]}
# 5、重启docker 服务
systemctl restart docker
docker start registry
首先我们拉取仓库镜像,并根据镜像启动私有仓库的容器,
然后我们启动服务器,访问宿主机ip的5000端口/v2/_catalog,验证私有仓库是否搭建成功,
搭建成功以后,我们还需要修改daemon.json文件,让docker信任私有仓库的地址,
然后我们重启docker服务就可以了,
7.2将镜像上传至私有仓库
# 1、标记镜像为私有仓库的镜像
docker tag centos:7 私有仓库服务器IP:5000/centos:7
# 2、上传标记的镜像
docker push 私有仓库服务器IP:5000/centos:7
上传成功以后可以访问宿主机ip的5000端口/v2/_catalog,查看私有仓库中的镜像,
7.3从私有仓库拉取镜像
#拉取镜像
docker pull 私有仓库服务器ip:5000/centos:7
八、Docker容器与传统虚拟机比较
容器就是将软件打包成标准化单元,以用于开发、交付和部署。
- 容器镜像是轻量的、可执行的独立软件包 ,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。
- 容器化软件在任何环境中都能够始终如一地运行。
- 容器赋予了软件独立性,使其免受外在环境差异的影响,从而有助于减少团队间在相同基础设施上运行不同软件时的冲突。
Docker容器虚拟化和传统虚拟机的相同点和不同点如下:
- 相同:
- 容器和虚拟机具有相似的资源隔离和分配优势
- 不同:
- 容器虚拟化的是操作系统,虚拟机虚拟化的是硬件。
- 传统虚拟机可以运行不同的操作系统,容器只能运行同一类型操作系统