项目部署问题:
大型项目组件非常多,特别是微服务项目。运行环境也很复杂。
每一个不同的组件应用,依赖不同的函数库。
- 依赖关系复杂
- 开发、测试、生成环境差异
Docker如何解决依赖的兼容问题的?
-
将应用的Libs ( 函数库)、Deps (依赖)配置与应用一起打包
-
将每个应用放到一个隔离容器去运行,避免互相干扰
Ubuntu和CentOS都是基于Linux内核,只是系统应用不同,提供的函数库有差异
Docker如何解决不同系统环境的问题?
- Docker将用户程序与所需要调用的系统(比如Ubuntu)函数库一起打包
- Docker运行到不同操作系统时,直接基于打包的库函数,借助于操作系统的Linux内核来运行
【Docker是一个快速交付应用、运行应用的技术】
1.可以将程序及其依赖、运行环境一 起打包为一个镜像,可以迁移到任意Linux操作系统
2.运行时利用沙箱机制形成隔离容器,各个应用互不干扰
3.启动、移除都可以通过一行命令完成,方便快捷
2.Docker和虚拟机的差别Docker初识:
Docker如何解决大型项目依赖关系复杂,不同组件依赖的兼容性问题?
Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像
Docker应用运行在容器中,使用沙箱机制,相互隔离
Docker如何解决开发、测试、生产环境有差异的问题(操作系统不一样)?
- Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行
虚拟机(virtual machine)是在操作系统中模拟硬件设备,然后运行另一个操作系统,比如在Windows系统里面运行Ubuntu系统,这样就可以运行任意的Ubuntu应用了。
Docker在执行时直接调用操作系统内核的,所以执行性能会比虚拟机快。
其他差异:
Docker只是封装了应用必须的函数库,体积往往比较小。容器都是MB级别,虚拟机至少几个G
3.Docker架构 镜像和容器总结:
Docker和虚拟机的差异:
- docker是一 个系统进程;虚拟机是在操作系统中的操作系统
- docker体积小、 启动速度快、性能好;虚拟机体积大、启动速度慢、性能一般
镜像(Image):Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。(镜像其实就是硬盘中的文件)
容器(Container): 镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器隔离,对外不可见。
镜像都是只读的,也就是说容器在运行过程中不能向镜像写东西。你可以基于镜像去创建容器,容器可以从里面读取数据但不能写。那我将来mysql数据往哪写呢?
很简单,你拷贝一份镜像数据到自己的container里面就行。
你在写数据写到自己空间里,不会对其他容器产生影响,也不会对镜像产生影响。
Docker和DockerHubDockerHub是一个Docker镜像的托管平台。 这样的平台称为Docker Registry。
国内也有类似于DockerHub的公开服务,比如网易云镜像服务、阿里云镜像库等。
隐私问题,可以搭建私有云。
Docker是一个CS架构的程序,由两部分组成:
- 服务端(server):docker守护进程,负责处理docker指令,管理镜像、容器等
- 客户端(client):通过命令或restAPI向docker服务端发送指令。可以在本地或远程向服务端发送指令。
使用docker,主要就是向dockerserver发命令,想办法得到镜像,不管用那种方式,然后再把镜像创建成容器运行,完成部署就可以了。
4.Docker的安装总结:
- 镜像:将应用程序及其依赖、环境、配置打包在一-起
- 容器:镜像运行起来就是容器,一个镜像可以运行多个容器
- Docker结构
- 服务端:接收命令或远程请求,操作镜像或容器
- 客户端:发送命令或者请求到Docker服务端
- DockerHub:一个镜像托管的服务器,类似的还有阿里云镜像服务,统称为DockerRegistry
安装Docker
企业部署一般都是采用Linux操作系统,而其中又数CentOS发行版占比最多,因此我们在CentOS下安装Docker。参考课前资料中的文档:
Docker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。
Docker CE 分为 stable test 和 nightly 三个更新频道。
官方网站上有各种环境下的 安装指南,这里主要介绍 Docker CE 在 CentOS上的安装。
1.CentOS安装DockerDocker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10, CentOS 7 满足最低内核的要求,所以我们在CentOS 7安装Docker。
1.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.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
docker-ce为社区免费版本。稍等片刻,docker即可安装成功。
1.3.启动dockerDocker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!
启动docker前,一定要关闭防火墙后!!
启动docker前,一定要关闭防火墙后!!
启动docker前,一定要关闭防火墙后!!
# 关闭 systemctl stop firewalld # 禁止开机启动防火墙 systemctl disable firewalld # 查看防火墙状态 systemctl status firewalld
通过命令启动docker:
systemctl start docker # 启动docker服务 systemctl stop docker # 停止docker服务 systemctl restart docker # 重启docker服务 systemctl status docker # docker状态
然后输入命令,可以查看docker版本:
docker -v
如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKwWUG0w-1637048353451)(F: 1黑马程序员SpringCloud 3assetsimage-20210418154704436.png)]
1.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
# 这里直到EOF都要复制
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://opirc3cp.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
镜像加速配置完成。
5.镜像命令镜像名称一般分两部分组成: [repository]:[tag]
tag:版本,mysql:5.7 / mysql:5.6是两个不同的镜像
获取镜像的方式:
-
本地:dockerFile 通过docker build构建镜像
-
远程:Docker Registry 镜像服务器 通过 docker pull 从服务器拉取镜像
查看镜像 : docker images
删除镜像:docker rmi
推送镜像到服务:docker push
保存镜像为一个压缩包:docker save
加载压缩包为镜像:docker load
查看帮助文档 : docker --help
案例从DockerHub中拉取一个nginx镜像并查看
-
首先去镜像仓库搜索nginx镜像,比如DockerHub:
-
拉取与查看
# 拉取nginx docker pull nginx # 查看镜像 docker images # 镜像内容 REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 04661cdce581 6 days ago 141MB
利用docker save将nginx镜像导出磁盘,然后再通过load加载回来
步骤一: 利用docker xx --help命令查看docker save和docker load的语法
步骤二: 使用docker tag创建新镜像mynginx1.0
步骤三: 使用docker save导出镜像到磁盘
[root@hadoop100 ~]# docker save --help Usage: docker save [OPTIONS] IMAGE [IMAGE...] Save one or more images to a tar archive (streamed to STDOUT by default) Options: -o, --output string Write to a file, instead of STDOUT
Save one or more images to a tar archive
将一个或多个图像保存到tar存档
docker save -o nginx.tar nginx:latest
[root@hadoop100 ~]# docker save -o nginx.tar nginx:latest [root@hadoop100 ~]# ll total 142484 -rw-------. 1 root root 145894912 Nov 15 18:09 nginx.tar
为了演示导入,先把nginx:latest镜像删除。
docker rmi nginx:latest
[root@hadoop100 ~]# docker rmi nginx:latest Untagged: nginx:latest Untagged: nginx@sha256:dfef797ddddfc01645503cef9036369f03ae920cac82d344d58b637ee861fda1 Deleted: sha256:04661cdce5812210bac48a8af672915d0719e745414b4c322719ff48c7da5b83 Deleted: sha256:89fa50132ae2bb56db192e9ab716c00d7af2af7cfd2e53d89d5d2fe5816cdbad Deleted: sha256:0e18e237ed37ff83d795813dec5318934ea8ee0ad4dc63ed3027c8b690196500 Deleted: sha256:cadf0f41ad2a811bd450c929e3a51afe060fbc0f4c3dd0e98cb73b8023877c12 Deleted: sha256:4cd32ed8e5340b498b9992d324ded5c047cc0e7d631bffeca0d0fa0f8a0def33 Deleted: sha256:d46a23eaf6e327713efe12221a2b77f2ce3eec8f68df165727fc0afde62c4a6b Deleted: sha256:e8b689711f21f9301c40bf2131ce1a1905c3aa09def1de5ec43cf0adf652576e
导入load命令的帮助
# 查看load命令帮助文档 docker load --help Usage: docker load [OPTIONS] Load an image from a tar archive or STDIN Options: -i, --input string Read from tar archive file, instead of STDIN -q, --quiet Suppress the load output
导入命令
docker load -i nginx.tar
[root@hadoop100 ~]# docker load -i nginx.tar e8b689711f21: Loading layer 83.86MB/83.86MB ea56d6ebf7e5: Loading layer 61.99MB/61.99MB 38aec0f8e5ed: Loading layer 3.072kB/3.072kB fc199aaed79a: Loading layer 4.096kB/4.096kB 921ee7f55927: Loading layer 3.584kB/3.584kB 280fbd619253: Loading layer 7.168kB/7.168kB Loaded image: nginx:latest镜像命令练习
去DockerHub搜索并拉取一个Redis镜像
1.去DockerHub搜 索Redis镜像
2.查看Redis镜像的名称和版本
3.利用docker pull命令拉取镜像
4.利用docker save命令将redis:latest打包为一个redis.tar包
5.利用docker rmi删除本地的redis:latest
6.利用docker load重新加载redis.tar文件
1.搜索
2,3.redis名称与版本、拉取
docker pull redis:latest
# 拉取最新版本redis docker pull redis:latest latest: Pulling from library/redis 7d63c13d9b9b: Already exists a2c3b174c5ad: Pull complete 283a10257b0f: Pull complete 7a08c63a873a: Pull complete 0531663a7f55: Pull complete 9bf50efb265c: Pull complete Digest: sha256:54ee15a0b0d2c661d46b9bfbf55b181f9a4e7ddf8bf693eec5703dac2c0f5546 Status: Downloaded newer image for redis:latest docker.io/library/redis:latest
4.打包
[root@hadoop100 ~]# docker save -o redis.tar redis:latest [root@hadoop100 ~]# ll total 256064 -rw-------. 1 root root 145894912 Nov 15 18:09 nginx.tar -rw-------. 1 root root 116304384 Nov 15 18:18 redis.tar
5.删除
[root@hadoop100 ~]# docker rmi redis:latest Untagged: redis:latest Untagged: redis@sha256:54ee15a0b0d2c661d46b9bfbf55b181f9a4e7ddf8bf693eec5703dac2c0f5546 Deleted: sha256:7faaec68323851b2265bddb239bd9476c7d4e4335e9fd88cbfcc1df374dded2f Deleted: sha256:e6deb90762475cda72e21895911f830ed99fd1cc6d920d92873270be91235274 Deleted: sha256:2649acad13241d9c8d81e49357bc66cce459b352ded7f423d70ede7bd3bb7b89 Deleted: sha256:64007bba5fc220df4d3da33cecdc2d55dd6a73528c138b0fa1acd79fd6a9c217 Deleted: sha256:b2cc2f1bf8b1cca8ba7c19e1697f7b73755903ad8f880b83673fd6a697aca935 Deleted: sha256:fbd1283ab782925be4d990bd4bebe9ad5e5cf9a525abfb6fa87465e072da9d31
6.加载
[root@hadoop100 ~]# docker load -i redis.tar b43651130521: Loading layer 338.4kB/338.4kB 8b9770153666: Loading layer 4.274MB/4.274MB 6b01cc47a390: Loading layer 27.8MB/27.8MB 0bd13b42de4d: Loading layer 2.048kB/2.048kB 146262eb3841: Loading layer 3.584kB/3.584kB Loaded image: redis:latest [root@hadoop100 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 04661cdce581 6 days ago 141MB redis latest 7faaec683238 4 weeks ago 113MB6.容器命令介绍
容器的三个状态:运行、暂停、停止
如果容器进入暂停状态、操作系统会将容器内的进程挂起,容器关联的内存暂存起来。CPU不再执行这个进程。但是如果你把它恢复了内存空间恢复,程序接着被运行,那么这个容器就一直运行状态了。但是停止则不同,操作系统直接杀死,容器所占的内存回收,保留下来的仅剩容器的文件系统。一旦停止你是没办法恢复的。docker start 意味着生成一个全新的进程。
docker rm 彻底删除。
7.容器命令案例1 创建运行一个Nginx容器1.去docker hub查看Nginx的容器运行命令
docker run --name containerName -p 80:80 -d nginx
docker run
–name : 容器名称
-p : 将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
比方说我有一台centos的服务器,是192.168.150.101,在这台服务器上部署了一个nginx容器,端口是80.
我们的用户想要访问nginx容器,能不能访问?
肯定不能。
容器对外是隔离的。
所以我们要做一个端口映射。比方说我们宿主机有很多端口,其中一个端口是80,我们让宿主机的80和容器的80产生一个映射,这样以来,任何进入宿主机80的请求,就都会被转发到容器的80端口,这样就等于是Nginx处理了请求。所以这个时候如果我们的客户想要访问容器,你访问这台宿主机就行。比如说:http://192.168.150.101:80,宿主机一看80,统一放到Nginx容器里去,于是容器就处理了。
所以端口映射的作用是什么?
是把一个本来完全隔离的容器,暴露一个端口,让你透过它来访问。如果没有它任何人无法访问容器。
80:80
左侧是宿主机端口(是可以任意编写的),右侧是容器内端口(一般是不变的)
-d : 代表后台运行容器,不加则是前台运行。在后台运行,即不想在前面看到它,让他在后面默默执行。
nginx: 镜像名称,没有写标签,是最新版
[root@hadoop100 ~]# docker run --name mn -p 80:80 -d nginx 8837ea3e6c6d1a830dd048e800be5be730920a60fda98e3bf127b84b455e45ba #容器的唯一ID
查看容器运行状态
[root@hadoop100 ~]# docker ps ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8837ea3e6c6d nginx "/docker-entrypoint.…" 28 seconds ago Up 27 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp mn
在宿主机访问一下,我这台centos虚拟机的ip地址是192.168.10.100,
我在window系统web访问的地址就应该是 http://192.168.10.100:80
容器部署成功
查看日志docker logs mn, mn是容器名
[root@hadoop100 ~]# docker logs mn /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2021/11/16 02:36:53 [notice] 1#1: using the "epoll" event method 2021/11/16 02:36:53 [notice] 1#1: nginx/1.21.4 2021/11/16 02:36:53 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 2021/11/16 02:36:53 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64 2021/11/16 02:36:53 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2021/11/16 02:36:53 [notice] 1#1: start worker processes 2021/11/16 02:36:53 [notice] 1#1: start worker process 31 192.168.10.1 - - [16/Nov/2021:02:39:23 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" "-" 2021/11/16 02:39:23 [error] 31#31: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.10.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.10.100", referrer: "http://192.168.10.100/" 192.168.10.1 - - [16/Nov/2021:02:39:23 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://192.168.10.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" "-"
我想要持续监控日志怎么设置?
docker logs -f mn
可以一直跟踪日志
8.容器命令案例2进入Nginx容器,修改HTML文件内容,添加信息
步骤一:进入容器。进入我们刚刚创建的nginx容器的命令为:
docker exec -it mn bash # docker exec : 进入容器内部,执行一个命令 # -it : 给当前进入的容器创建一个标准输入、输出终端,允许我们与容器交互。 # mn : 容器名称 # bash : 进入容器后执行的命令,bash是一个linux终端交互命令。如果你有其他的命令要执行,这里也可以修改成你要执行的命令。
[root@hadoop100 ~]# docker exec -it mn bash root@8837ea3e6c6d:/# root@8837ea3e6c6d:/# cd /usr/share/nginx/html/ root@8837ea3e6c6d:/usr/share/nginx/html# ls 50x.html index.html
容器的内部其实会有自己的一套文件系统(阉割版)
sed -i 's#Welcome to nginx#哈哈哈哈哈#g' index.html sed -i 's###g' index.html
exit # 退出容器 docker stop mn # 停止mn容器运行 docker ps -a # 查看所有包括停止的容器信息 docker start mn # 运行mn容器 docker rm -f mn # 强制删除mn
进入容器:
- 命令是docker exec -it [容器名] [要执行的命令]
- exec命令可以进入容器修改文件,但是在容器内修改文件是不推荐的I
创建并运行一个redis容器,并且支持数据持久化
步骤一: 到DockerHub搜索Redis镜像
步骤二: 查看Redis镜像文档中的帮助信息
步骤三: 利用docker run命令运行一个Redis容器
docker run --name some-redis -d redis # 用这个,配置好端口映射,myredis容器名 docker run --name myredis -p 6379:6379 -d redis redis-server --appendonly yes [root@hadoop100 ~]# docker run --name myredis -d redis 833f9c68d82ff2e4f08f6ae6e173c4a0651be0ab401f27fd00a697e946f9f599
在我的windows拦截redis的地址应该是 192.168.10.100:6379
进入redis容器,并执行redis-cli客户端命令,存入num=666
docker exec -it myredis bash # 直接进入redis-cli方式 docker exec -it myredis redis-cli root@833f9c68d82f:/data# ls root@833f9c68d82f:/data# redis-cli 127.0.0.1:6379> set mynum 666 OK 127.0.0.1:6379> get mynum "666" 127.0.0.1:6379>10.数据卷命令
发现一个问题,容器和数据是耦合的,因此带来很多问题。
1.不便于修改:如我们该nginx的html需要进入容器内部修改
2.数据不可复用:容器内的修改对外是不可见的。所有修改对新创建的容器是不可复用的。
3.升级维护困难:数据在容器内,如果要升级容器必然删除旧容器,所有数据都跟着删除了。
数据卷(volume): 是一个虚拟目录,指向宿主机文件系统中的某个目录。
操作数据卷:
docker volume [command] #create 创建volume #inspect 显示一个或多个volume信息 #ls 列出所有的volume #prune 删除未使用的volume #rm 删除一个或多个指定的volume
案例:
创建一个数据卷,并查看数据卷在宿主机的目录位置
-
创建数据卷
docker volume --help # 创建数据卷 docker volume create html # 查看数据卷 docker volume ls # 查看数据卷详细信息 docker volume inspect html # 删除未使用的数据卷 docker volume prune # 删除html这个数据卷 docker volume rm html
11.数据卷挂载案例1总结:
1.数据卷的作用:
- 将容器与数据分离,解耦合,方便操作容器内数据保证数据安全。
2.数据卷操作
- docker volume create
- docker volume ls
- docker volume inspect
- docker volume rm
- docker volume prune
创建一个nginx容器,修改容器内的html目录内的index.html内容
需求说明:上个案例中,我们进入nginx容器内部,已经知道nginx的html目录所在位置/usr/share/ nginx/html,我们需要把这个目录挂载到html这个数据卷上,方便操作其中的内容。
提示: 运行容器时使用-V参数挂载数据卷
# 创建一个名为mn的nginx的容器,将镜像内/usr/share/nginx/html的内容挂载到html数据卷上
docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx
docker ps
...
196bd4eaba5b nginx "/docker-entrypoint.…" 8 seconds ago Up 7 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp mn
docker inspect html
[
{
"CreatedAt": "2021-11-15T19:22:34-08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": {},
"Scope": "local"
}
]
修改内容方式一
cd /var/lib/docker/volumes/html/_data vim index.html
方式二,采用XFTP 直接改/var/lib/docker/volumes/html/_data 目录下的内容即可
修改后
现在直接可以在高级编辑工具里修改!
现在测试一下 数据卷是不存在的情况:
如果容器运行时volume不存在,会自动被创建出来!【所以我们没必要自己创建数据卷】
- 先删除刚运行的容器
docker rm -f mn mn [root@hadoop100 _data]# docker volume prune WARNING! This will remove all local volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: html Total reclaimed space: 1.144kB [root@hadoop100 _data]# docker volume ls DRIVER VOLUME NAME local 6a77edff06b613d92e73d319467ce40616ba6fb002774d2bdc227b4b03108181 [root@hadoop100 _data]#
2.运行
docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx
访问网页,可行!
12.数据卷挂载案例2如果我们数据卷不存在,docker会自动帮你把数据卷创建出来。
创建并运行一个MySQL容器,将宿主机目录直接挂载到容器
提示:目录挂载与数据卷挂载的语法是类似的:
-V [宿主机目录]:[容器内目录]
-V [宿主机文件]:[容器内文件]
实现思路如下:
1.在将课前资料中的mysql.tar文件上传到虚拟机,通过load命令加载为镜像
2.创建目录/tmp/myql/data
3.创建目录/tmp/myql/conf,将课前资料提供的hmy.cnf文件上传到/tmp/mysql/conf
4.去DockerHub查阅资料, 创建并运行MySQL容器,要求:
①挂载/tmp/ myql/data到mysql容器内数据存储目录
②挂载/tmp/ myql/conf/hmy.cnf到mysql容器的配置文件
③设置MySQL密码
将mysql.tar导入到/opt/software目录
docker load -i mysql.tar
2. 创建目录[root@hadoop100 software]# mkdir -p mysql/data [root@hadoop100 software]# mkdir -p mysql/conf
/opt/software/mysql/conf下上传hmy.cnf
3.运行mysql容器docker run --name mymysql -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 -v /opt/software/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf -v /opt/software/mysql/data:/var/lib/mysql -d mysql:5.7.25
前面是宿主机地址,后面是Mysql的地址
-v /opt/software/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf 配置文件
-v /opt/software/mysql/data:/var/lib/mysql 数据文件
所有的数据都挂载到了data目录下
测试用navicat连接一下
192.168.10.100:3306
13.自定义镜像总结
- docker run的命令中通过-V参数挂载文件或目录到容器中:
①-V volume名称:容器内目录
②-V 宿主机文件:容器内文件
③-V 宿主机目录:容器内目录- 数据卷挂载与目录直接挂载的
①数据卷挂载耦合度低,由docker来管理目录,但是目录较深,不好找
②目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看
Dockerfile自定义镜像,我们以后直接写的微服务就需要自己定义镜像。之前学习的都是官方的镜像
13.1 镜像结构镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。
系统函数库、环境、配置、依赖,这就是镜像的组成,而我们说结构,还需要了解他们是怎么组成的。
这些的组成他们有没有相互的依赖关系或顺序呢?显然是有的,如果没有最底层的系统函数库,底层的文件系统,你怎么样去完成环境的配置?如果没有配置环境变量,你怎么做依赖的安装呢?如果没有依赖的安装,你怎么完成应用的安装呢?如果没有应用安装,你怎么做应用的配置呢?可见,镜像不仅仅是把这一堆的东西糅在一起。
接下来以mysql为例,将mysql镜像打散。
-
基础镜像:应用依赖的系统函数库,环境,配置,文件
-
层:在基础镜像基础上添加安装包、依赖、配置等,每次操作都形成新的一层。
如果分层了,整完基础、配置、文件都分为独立一层,我现在想构建5.8,也就上面几层不想要了,下面几层还是可以用的,我可以基于他们往上构建,提供一定复用性。【我们自己构建镜像,也应该从基础开始,逐层构建】
-
入口:镜像运行入口,一般是程序启动的脚本和参数
13.2 Dockerfile总结:
镜像是分层结构,每一-层称为一个Layer
- baselmage层: 包含基本的系统函数库、环境变量、文件系统
- Entrypoint: 入口,是镜像中 应用启动的命令
- 其它: 在baselmage基础上添加依赖、安装程序、完成整个应用的安装和配置
什么是Dockerfile
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
- FROM centos:6 表示基于centos6去构建基础镜像
- ENV key value 表示是键值对
- COPY ./mysql-5.7.rpm /tmp 本地拷贝到镜像里
- RUN 一般是安装命令
- EXPOSE 暴露端口,只是指定容器内监听的是什么端口,是给镜像使用者看,使用者一看是8080,那我-p参数:后面那一部分就必须写8080
比如说这条命令:docker run --name containerName -p 80:80 -d nginx,冒号后面的值就必须写8080.(EXPOSE 加或者不加其实都可以,加的话,镜像使用者看了能够明白) - ENTRYPOINT:启动命令
更新详细语法说明,请参考官网文档: https://docs.docker.com/engine/reference/builder
基于Ubuntu镜像构建一个新镜像, 运行一个java项目
步骤1:新建一个空文件夹docker-demo
步骤2:拷贝课前资料中的docker-demo.jar文件到docker-demo这个目录
步骤3:拷贝课前资料中的jdk8.tar.gz文件到docker-demo这个目录
步骤4:拷贝课前资料提供的Dockerfile到docker-demo这个目录
步骤5:进入docker-demo
步骤6:运行命令:docker build -t javaweb:1.0
我们观察一下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
打开xshell, 先在某个目录下创建dockerdemo,上传jdk,jar,dockerfile
执行如下命令,在docker-demo文件下。其中 -t 是 -tag的缩写,javaweb和1.0可以任意取。
【最后有一个点,代表dockerfile的位置】
docker build -t javaweb:1.0 .
运行
docker run --name web -p 8090:8090 -d javaweb:1.0
访问 http://192.168.10.100:8090/hello/count 能够访问。说明项目已经成功构建镜像,并部署到服务器了。
观察一下dockerfile,发现,除了copy指令,其他的指令都应该是可以复用的。那么能不能把其他除了部署jar的指令以外的指令,先行打包好称为一个镜像。后面直接部署jar呢?
基于java:8-alpine镜像,将一个Java项目构建为镜像
这个镜像已经帮我们把前n步给做完了。我们构建时以java:8-alpine 为基础时,就可以省去一大部分的安装JDK
修改后的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 .
[root@hadoop100 docker-demo]# docker build -t javaweb:2.0 . Sending build context to Docker daemon 211.1MB Step 1/4 : FROM java:8-alpine # 只需要4步就能拉取完成了!!!
实现思路如下:
①新建一个空的目录,然后在目录中新建一个文件,命名为Dockerfile
②拷贝课前资料提供的docker-demojar到这个目录中
③编写Dockerfile文件:
- 基于java:8-alpine作 为基础镜像
- 将app.jar拷 贝到镜像中
- 暴露端口
- 编写入口ENTRYPOINT
④使用docker build命令构建镜像
⑤使用docker run创建容器并运行
14.DockerCompose 14.1 初始化Compose我们学了这么多,但是这些步骤都是我们手动一个个去部署的,在实际生产环境下,我们微服务的数量是非常多的。不可能一个个去构建!所以,我们必须要有一个集群部署的手段。 ——Compose
DockerCompose 是什么?
Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动-一个个创建和运行容器!
【分布式应用部署的帮手】
Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。
就是将之前的docker run命令变成一种便于观察的yml格式
对比之前的书写
# mysql 容器 docker run --name mymysql -e MYSQL_ROOT_PASSWORD=123 -p 3306:3306 -v /opt/software/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf -v /opt/software/mysql/data:/var/lib/mysql -d mysql:5.7.25 # 构建镜像 docker build -t web:1.0 # 运行容器 docker build -t javaweb:2.0 .
模板
version: "3.8"
services:
mysql:
image: mysql:5.7.25
environment:
MYSQL_ROOT_PASSWORD: 123
volumes:
- /opt/software/mysql/data:/var/lib/mysql
- /opt/software/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf
web:
build: .
ports:
- 8090:8090
mysql 仅仅是供给给集群内的服务用的,因此无需暴露端口,内部能访问就行了。
volumes 两个数据卷配置,具体配置内容是和之前完全一样的。
dockerCompose就是把docker run 各种参数转换成指令去执行的。
DockerCompose的详细语法参考官网: https://docs.docker.com/compose/compose-file/
将资料里的docker-compose,上传到/user/local/bin/目录
修改文件权限
chmod +x /usr/local/bin/docker-compose
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
14.2 初始化微服务集群总结:
DockerCompose有什么作用?
帮助我们快速部署分布式应用,无需-一个个微服务去构建镜像和部署。
将之前学习的cloud-demo微服务集群利用DockerCompose部署
第一步查看课前资料提供的cloud-demo文件夹,里面已经编写好了docker-compose文件
观察docker-compose.yml
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"
docker-compose在底层实现了服务间访问地址的转变,比如说,gateway想要访问orderservice服务,可以用服务名代替ip地址。我们之前在项目中用都是用localhost写的ip地址。我们需要去修改一下,改成服务名。
第二步修改自己的cloud-demo项目,将数据库、nacos地址都命名为docker-compose中的服务名
改动1:
user-service / bootstrap.yml
server-addr: localhost:8848 server-addr: nacos:8848
改动2:
user-service / applicaiton.yml
url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
url: jdbc:mysql://mysql:3306/cloud_user?useSSL=false
改动3:
order-service / application.yml
url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false url: jdbc:mysql://mysql:3306/cloud_order?useSSL=false server-addr: localhost:8848 server-addr: nacos:8848
改动4:
gateway / application.yml
server-addr: localhost:8848 server-addr: nacos:8848第三步
使用maven打包工具,将项目中的每个微服务都打包为app.jar
观察 user-service 的pom.xml存在以下内容,打包文件名被设置为了app。并将这个配置复制到order-service,gateway
app org.springframework.boot spring-boot-maven-plugin
将项目中打包生成的app.jar分别复制到cloud-demo各自的文件夹下
万事俱备!
第四步将cloud-demo上传至虚拟机,利用docker-compose up -d来部署
docker-compose up -d
查看日志
docker-compose logs -f
报错
Caused by: java.lang.reflect.UndeclaredThrowableException: null gateway_1 | at org.springframework.util.ReflectionUtils.rethrowRuntimeException(ReflectionUtils.java:147) ~[spring-core-5.2.13.RELEASE.jar!/:5.2.13.RELEASE] gateway_1 | at com.alibaba.cloud.nacos.registry.NacosServiceRegistry.register(NacosServiceRegistry.java:83) ~[spring-cloud-starter-alibaba-nacos-discovery-2.2.5.RELEASE.jar!/:2.2.5.RELEASE]
因先是userservice启动,往下才是nacos启动,nacos启动太慢。生成部署时,nacos环境应先部署,而后再去部署微服务
重启除了nacos外的微服务
docker-compose restart gateway userservice orderservice
访问报错,权限问题
### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Access denied for user 'root'@'172.18.0.2' (using password: YES)] with root cause
进入运行中的mysql容器,进入mysql
# 如果你需要修改mysql密码请执行,【password('这里是你的新密码')】
set password for root @localhost = password('root');
# by 'root' 中root是你的新密码
grant all privileges on *.* to root@'%' identified by 'root' with grant option;
# 刷新权限
flush privileges;
然后再访问地址:
http://192.168.10.100:10010/user/2?authorization=admin
访问成功
15.镜像仓库镜像仓库( Docker Registry )有公共的和私有的两种形式:
公共仓库:例如Docker官方的Docker Hub,国内也有-些云服务商提供类似于Docker Hub的公开服务,比如网易云镜像服务、DaoCloud 镜像服务、阿里云镜像服务等。
除了使用公开仓库外,用户还可以在本地搭建私有Docker Registry。 企业自己的镜像最好是采用私有Docker
Registry来实现。
配置Docker信任地址搭建私有镜像仓库
我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:
# 打开要修改的文件 vi /etc/docker/daemon.json # 添加内容: "insecure-registries":["http://192.168.10.100:8080"] # 重加载 systemctl daemon-reload # 重启docker systemctl restart docker
新建个文件夹mkdir registry-ui
新建个文件 touch docker-compose.yml
将以下内容写入该文件
带有图形化界面版本
使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:
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
执行
docker-compose up -d
开始构建一个私有仓库
访问 http://192.168.10.100:8080
如何上传镜像到私有仓库?
打包
[root@hadoop100 registry-ui]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE cloud-demo_gateway latest b4732b29dd7a 47 minutes ago 185MB cloud-demo_orderservice latest 6e5ed0e753d3 48 minutes ago 187MB cloud-demo_userservice latest 818b29d17379 48 minutes ago 184MB javaweb 2.0 355e1a3a0444 2 hours ago 171MB javaweb 1.0 7bc0acdff822 2 hours ago 722MB registry latest b8604a3fe854 3 days ago 26.2MB nginx latest 04661cdce581 6 days ago 141MB redis latest 7faaec683238 4 weeks ago 113MB ubuntu 16.04 b6f507652425 2 months ago 135MB nacos/nacos-server latest bdf60dc2ada3 3 months ago 1.05GB joxit/docker-registry-ui static c97caf4d3877 6 months ago 24.5MB mysql 5.7.25 98455b9624a9 2 years ago 372MB java 8-alpine 3fd9dd82815c 4 years ago 145MB [root@hadoop100 registry-ui]# docker tag nginx:latest 192.168.10.100:8080/nginx:1.0
ID都是一样的
192.168.10.100:8080/nginx 1.0 04661cdce581 6 days ago 141MB nginx latest 04661cdce581 6 days ago 141MB
推送镜像
docker push 192.168.10.100:8080/nginx:1.0
拉取镜像
docker pull 192.168.10.100:8080/nginx:1.0
测试拉取之前先把本地的删除掉
docker rmi 192.168.10.100:8080/nginx:1.0其他
简化版镜像仓库
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 可以查看当前私有镜像服务中包含的镜像



