Docker操作手册
内容
前言... 2
基本原理... 2
Docker VS 虚拟机... 3
一. 安装镜像... 4
二. 创建包含指定JDK的镜像... 5
三. 容器的创建和使用... 7
一):创建eureka的容器并使用... 7
二):创建feign1的容器并使用... 9
三):创建feign2的容器并使用... 11
四. 创建可用镜像,并部署到其他服务器... 11
前言
Docker:一个开源的软件项目,让用户程序部署在一个相对隔离的环境运行,借此在Linux操作系统上提供一层额外的抽象,以及操作系统层虚拟化的自动管理机制。需要额外指出的是,Docker并不等于容器(containers),Docker只是容器的一种,其他的种类的容器还有Kata container,Rocket container等等。
镜像:镜像也是 docker 的核心组件之一,镜像时容器运行的基础,容器是镜像运行后的形态。总体来说,镜像是一个包含程序运行必要以来环境和代码的只读文件,它采用分层的文件系统,将每一层的改变以读写层的形式增加到原来的只读文件上。容器在启动或者创建时,必须指定一个镜像的名称或者 id ,其实,这时镜像所扮演的角色就是容器的模版,不同的镜像可以构造出不同的容器,同一个镜像,我们也可以通过配置不同参数来构造出不通的容器。
基本原理
Docker利用Linux中的核心分离机制,例如Cgroups,以及Linux的核心Namespace(名字空间)来创建独立的容器。一句话概括起来Docker就是利用Namespace做资源隔离,用Cgroup做资源限制,利用Union FS做容器文件系统的轻量级虚拟化技术。Docker容器的本质还是一个直接运行在宿主机上面的特殊进程,看到的文件系统是隔离后的,但是操作系统内核是共享宿主机OS,所以说Docker是轻量级的虚拟化技术。
Docker VS 虚拟机
从上面这幅图就可以看出,虚拟机是正儿八经的存在一层硬件虚拟层,模拟出了运行一个操作系统需要的各种硬件,例如CPU,MEM,IO等设备。然后在虚拟的硬件上安装了一个新的操作系统Guest OS。所以在Windows宿主机上面可以跑Linux虚拟机。因为多了一层虚拟,所以虚拟机的性能必然会有所损耗。Docker容器是由Docker Deamon(Docker Deamon是运行在宿主机上面的一个后台进程,负责拉起和设置容器)拉起的一个个进程,通过Docker Deamon设置完Namespace和Cgroup之后,本质上就是一个运行在宿主机上面的进程。因为没有一层虚拟的Guest OS,所以Docker轻量级很多。但是有利就有弊,由于Docker 容器直接运行在宿主机上面,安全性就相对较差些,另外也没有办法在Windows上面运行Linux的容器,如果容器里面的应用对特定系统内核有要求也不能运行在不满足要求的宿主机上面。
| docker | 虚拟机 | |
| 相同点 | 1. 都可在不同的主机之间迁移 | |
| 操作系统 | 在性能上有优势,可以轻易的运行多个操作系统 | 可以安装任何系统,但是性能不及容器 |
| 原理 | 和宿主机共享内核,所有容器运行在容器引擎之上,容器并非一个完整的操作系统,所有容器共享操作系统,在进程级进行隔离 | 每一个虚拟机都建立在虚拟的硬件之上,提供指令级的虚拟,具备一个完整的操作系统 |
| 优点 | 高效、集中。一个硬件节点可以运行数以百计的的容器,非常节省资源,QoS 会尽量满足,但不保证一定满足。内核由提供者升级,服务由服务提供者管理 | 对操作系统具有绝对权限,对系统版本和系统升级具有完全的管理权限。具有一整套的的资源:CPU、RAM 和磁盘。QoS 是有保证的,每一个虚拟机就像一个真实的物理机一样,可以实现不同的操作系统运行在同一物理节点上。 |
| 资源管理 | 弹性资源分配:资源可以在没有关闭容器的情况下添加,数据卷也无需重新分配大小 | 虚拟机需要重启,虚拟机里边的操作系统需要处理新加入的资源,如磁盘等,都需要重新分区。 |
| 远程管理 | 根据操作系统的不同,可以通过 shell 或者远程桌面进行 | 远程控制由虚拟化平台提供,可以在虚拟机启动之前连接 |
| 缺点 | 对内核没有控制权限,只有容器的提供者具备升级权限。只有一个内核运行在物理节点上,几乎不能实现不同的操作系统混合。容器提供者一般仅提供少数的几个操作系统 | 每一台虚拟机都具有更大的负载,耗费更多的资源,用户需要全权维护和管理。一台物理机上能够运行的虚拟机非常有限 |
| 配置 | 快速,基本上是一键配置 | 配置时间长 |
| 启动时间 | 秒级 | 分钟级 |
| 硬盘使用 | MB | GB |
| 性能 | 接近原生态 | 弱于原生态 |
| 系统支持数量 | 单机支持上千个 | 一般不多于几十个 |
- 安装镜像
1:一定要切换成root用户
sudo su –
输入密码:******
2:安装docker
更新每个软件包的最新信息,从而正确地下载最新版本的软件。
apt-get update
下载并安装docker
apt-get install docker.io
3:查看安装版本,可验证是否安装成功
docker -v
返回信息
docker version 20.10.7, build 20.10.7-0ubuntu5~20.04.2
4:登录(部分镜像下载需要登陆后才可,本示例中ubuntu镜像可不登陆直接下载)
docker login
根据提示数据用户名和密码
提示:docker镜像仓库地址:Docker Hub,未注册docker的可直接进行注册并查找镜像
返回部分信息
Login Succeeded
5:下载ubuntu作为基础镜像
docker pull ubuntu:20.04
返回部分信息
Status: Downloaded newer image for ubuntu:20.04
docker.io/library/ubuntu:20.04
6:查看已下载的镜像
docker images
返回信息
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 20.04 ba6acccedd29 3 weeks ago 72.8MB
- 创建包含指定JDK的镜像
1:上传JDK安装包
2:编写DockerFile(在JDK同级目录下编写Dockerfile文件)
使用touch 命令,创建Dockerfile,并编写脚本,脚本如下:
#!/bin/bash
# 使用Ubuntu作为基础镜像(如果本地不存在依赖镜像的时候会下载相应镜像)
FROM ubuntu:20.04
# 维护人信息
MAINTAINER panpan.qi
# 切换到usr/local 目录下
WORKDIR ./usr/local
# 创建jdk目录
RUN mkdir jdk
# 对jdk赋权
RUN chmod 777 /usr/local/jdk
# 将下载的jdk 的压缩包拷贝到镜像中,注意 ADD和COPY的区别,ADD 会解压,COPY不会解压, 注意:jdk*.tar.gz使用的是相对路径
ADD jdk-11.0.12_linux-x64_bin.tar.gz /usr/local/jdk
# 设置JAVA_HOME 的环境变量(如果不确定最后的JDK解压后的文件夹,可以先执行tar -zxvf jdk-11.0.12_linux-x64_bin.tar.gz,JDK安装包就会被解压,ll查看目录即可)
ENV JAVA_HOME=/usr/local/jdk/jdk-11.0.12
# 设置JAVA 环境
ENV CLASSPATH=$JAVA_HOME/bin:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
# 将java可执行文件设置到PATH中,这样就可以使用java命令了
ENV PATH=.:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
# 向外暴露端口8088 ,这里只是演示,没有其他作用;
#EXPOSE 8088
# 容器启动自动启动shell脚本
COPY start.sh /root/start.sh
RUN chmod +x /root/start.sh
ENTRYPOINT cd /root; ./start.sh
# 执行java -version 命令
CMD ["java","-version"]
3:docker build -f Dockerfile -t jdk11:v1.0 .
-t jdk8:v1.0 给新构建的镜像取名为 jdk8, 并设定版本为 v1.0
注意最后有个点,代表使用当前路径的 Dockerfile 进行构建
返回部分信息
Successfully built 740c5aab4f3c
Successfully tagged jdk11:v1.0
4:查看已下载的镜像
docker images
返回信息
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk1102 v1.0 740c5aab4f3c 7 minutes ago 381MB
jdk11 v1.0 740c5aab4f3c 7 minutes ago 381MB
ubuntu 20.04 ba6acccedd29 3 weeks ago 72.8MB
5:删除多余镜像(因测试本地镜像创建,所以多运行了一次DockerFile,现删除多余镜像)
命令:docker rmi 镜像id
例:docker rmi 740c5aab4f3c
此时会报错:Error response from daemon: conflict: unable to delete 740c5aab4f3c (must be forced) - image is referenced in multiple repositories
表明有多个镜像的ID重复,此时可根据"REPOSITORY:TAR"进行删除
docker rmi jdk1102:v1.0
- 容器的创建和使用
注意:本案例中已springCloud的eureka(注册中心)和feign为例,且可实现feign2调用feign1的功能
一):创建eureka的容器并使用
1:创建容器并绑定宿主机端口
方法一:(下面的步骤都按照该方法进行操作, 主要是容器的名称eurekahost)
docker run -dit --restart=unless-stopped --name eurekahost --net=host jdk11:v1.0 /bin/bash
方法二:
docker run -dit --restart=unless-stopped --name eurekanet -p 8700:8700 -p 8702:8702 -p 8703:8703 jdk11:v1.0 /bin/bash
命令解释:
-d 代表后台运行,
-it 表示可以交互,
--net 指定容器的网络模式(详细请百度)
host模式:使用 --net=host 指定。(直接使用宿主机网络,容器间直接即可相互调用)
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,默认设置。
container模式:使用 --net=container:NAME_or_ID 指定(指定当前创建容器与某个容器共享网络)
-p 为端口映射(将容器端口映射到宿主主机)
--restart=unless-stopped 在容器退出时总是重启容器,此方式在容器内ctrl+d退出后会重启容器,ctrl+p+q则仍旧正常运行容器
--name 指定容器名称
jdk11:v1.0 指定镜像的REPOSITORY和TAG
/bin/bash可以让容器不启动后立马就停止
2:查看容器状态
doker ps -a
-a:查看全部,不加-a,默认只查看已启动的容器
返回信息
3:复制jar包到容器内
文件拷贝命令
宿主机->容器:docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径
容器->宿主机:docker cp 容器名:要拷贝到容器里面对应的路径 要拷贝的文件路径
docker cp /home/ubuntu/eureka.jar eurekahost:/tmp/
4:进入到容器内(执行此命令后用户会进入到容器内)
docker attach eurekahost
5:移动拷贝到容器内的jar包(jar包内指定了8700端口)到想要放置的目录下,并进入到该目录
cd /usr/local/
mkdir java
mv /tmp/eureka.jar java/
cd java/
6:运行jar包
nohup java -jar eureka.jar >/dev/null 2>&1 &
7:查看jar包运行状态
ps -ef|grep java
返回结果
8:退出容器(此命令会退出容器)
方法一:ctrl+d 退出后容器会默认关闭,但是创建容器时加了参数--restart=unless-stopped,所以容器会自动重启
方法二:ctrl+p+q 退出后容器正常运行,路径发生变化(强烈推荐)
9:确认宿主机与容器的jar端口进行了绑定
wget http://localhost:8700/
返回信息
10:查看宿主机IP
Ifconfig
11:根据宿主机IP在其他机器上进行端口访问测试
http://192.168.91.129:8700/
二):创建feign1的容器并使用
1:创建容器并绑定宿主机端口
方法一【配合 一):创建eureka的容器并使用 步骤1的方法一】:
docker run -dit --restart=unless-stopped --name feign1service2host --net=host jdk11:v1.0 /bin/bash
方法二【配合 一):创建eureka的容器并使用 步骤1的方法二】:
docker run -dit --restart=unless-stopped --name feign1service2net --net=container:eurekanet jdk11:v1.0 /bin/bash
2:重复上记一的2~8步骤,进行feign1service2的容器创建和使用
3:确认宿主机与容器的jar端口进行了绑定
wget http://localhost:8702/feign1/getList
返回信息
4:查看根据宿主机的eureka,会发现feign已成功注册
5:根据宿主机IP在其他机器上进行端口访问测试,可成功访问
http://192.168.91.129:8702/feign1/getList
三):创建feign2的容器并使用
1:根据【二):创建feign1的容器并使用】进行feign2的1~2创建和校验
2:确认宿主机与容器的jar端口进行了绑定
wget http://localhost:8703/feign2/getList
返回信息
3:查看根据宿主机的eureka,会发现feign已成功注册
4:根据宿主机IP在其他机器上进行端口访问测试,可成功访问(且该接口还调用了feign1的接口)
http://192.168.91.129:8703/feign2/getList
- 根据容器创建可用镜像并导出,再部署到其他服务器
1:容器保存为镜像
docker commit eurekahost eurekahost
docker commit feign1service2host feign1service2host
docker commit feign2servicehost feign2servicehost
2:镜像查看
docker images
返回信息
3:镜像的保存
docker save eurekahost > eurekahost.tar
docker save feign1service2host > feign1service2host.tar
docker save feign2servicehost > feign2servicehost.tar
4:将上记步骤3的3个文件导出到其他服务器上
5:按照【一. 安装镜像】的1~3安装docker,已经安装请绕过
6:镜像的导入
docker load -i eurekahost.tar
docker load -i feign1service2host.tar
docker load -i feign2servicehost.tar
7:创建容器(以上记步骤6的eureka为例)
docker run -dit --restart=unless-stopped --name eurekahost --net=host eurekahost:latest /bin/bash
8:进入容器,并启动jar包
docker attach eurekahost
cd /usr/local/java/
nohup java -jar eureka.jar >/dev/null 2>&1 &
9:依次启动feign1,feign2的jar包,会发现未注册eureka成功
调查原因:是因为在feign1和feign2内写死了eureka的注册地址IP,将其修改为新服务器的IP即可
如果其他配置信息有变化,也要对应修改,比如数据库IP
改为
重新启动feign1和feign2的jar
正常注册及访问



