Docker基础
基础知识
核心思想:打包装箱,每个箱子相互隔离
docker是基于Go语言开发的
虚拟机和容器的区别
虚拟机的缺点
- 资源占用多
- 冗余步骤多
- 启动很慢
容器化技术
docker特点:
- 容器内应用直接运行在宿主机的内核,容器没有自己的内核,也没有虚拟硬件,较为轻便
- 每个容器之间相互隔离,每个容器都有一个独立的文件系统,互不影响
- 更简单的运维:
- 打包镜像发布测试,一键运行
- 更便捷的升级和扩容,测试环境高度一致
- 更高效的计算资源利用:内核级的虚拟化
docker的组成
安装docker
环境是阿里云ESC的CentOS7,操作系统不同可能指令略有差别
检测系统版本
1 | cat /etc/redhat-release #检测CentOS系统版本 |
安装准备环境
1 | # -y表示所有的询问都默认选yes |
安装
1 | #卸载之前环境(如果存在) |
启动docker
1 | #启动 |
docker默认工作路径/var/lib/docker
阿里云镜像加速
1 | sudo mkdir -p /etc/docker |
Docker运行原理
docker run的运行流程
Docker是一个CS结构的系统,docker的守护进程运行在主机上,通过socket从客户端访问
DockerServer接收Docker Client的命令并执行
Docker为什么比虚拟机快?
- Docker比VM抽象层更少
- 新建容器时,docker不需要像VM那样重新加载一个操作系统,避免引导,而docker是基于宿主机,资源占用更少
常用命令
系统命令
帮助文档地址Reference documentation | Docker Documentation
1 | docker version #版本 |
设置开机自启动
1
2
3
4
5
6#设置docker开机自启
systemctl enable docker
#运行容器时设置开机自启
docker run --restart=always 容器名称或容器ID
#未运行容器时设置开机自启
docker update --restart=always 容器名称或容器ID
镜像命令
查看镜像
1
2
3docker images #查看所有镜像
-a #显示所有镜像
-q #只显示镜像id搜索镜像(也可以手动在dockerhub上搜索)
1
2docker search 镜像名 #在dockerhub上搜索镜像名
--filter=STARS=3000 #搜索stars大于3k的镜像下载镜像
1
2
3docker pull 镜像名 #下载镜像
#例
docker pull mysql:latest #可以通过[:tag]来指定版本删除镜像
1
2docker rmi 镜像id #删除指定id的镜像
docker rmi -f ${docker images -aq} #删除所有镜像自定义新建镜像
类似于VM的快照机制
1
2#原理与Git类似,注意只能提交有运行记录的容器
dockerc commit -m="描述信息" -a="作者" 容器id 目标镜像名 :[TAG]我们commit过的容器将成为新的镜像保存在本地
容器命令
运行容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15docker run 镜像名或id #启动指定镜像
#一些常用参数
--name="" #指定容器名称,用于区分容器
-d #后台方式运行
-it #交互式运行,进入容器查看内容
-p #指定端口
-p ip:主机端口:容器端口 #绑定主机ip,端口与容器端口
-p 主机端口:容器端口 #绑定主机端口与容器端口,如8080:8080
-p 容器端口 #仅设定容器端口(外部无法连接)
-P #随机指定端口
--rm #测试运行,用完即删
--net #指定运行网路(一般用于自定义网络)
--restart=always #开机自启
-e #一些额外参数查看容器
1
2
3
4docker ps #查看正在运行的容器
-a #查看运行记录
-n=num #显示num个最近创建的容器
-q #仅显示容器编号进入容器
1
2
3
4
5
6
7
8#退出交互式容器
exit #容器停止
[ctrl] + [P] +[Q] #退出交互式,但容器不停止
#进入交互式容器并开启新的终端
docker exec -it 容器id /bin/bash
#进入容器正在执行的终端,不会启动新的进程
docker attach 容器id删除容器
1
2docker rm #删除容器
docker rm -f ${docker ps -aq} #删除所有容器启动和重启
1
2
3
4docker start 容器id #启动容器(需要能在运行记录中找到id)
docker restart 容器id #重启容器
docker stop 容器id #停止
docker kill 容器id #强制停止查看信息
1
2docker top 容器id #查看容器内部的进程信息
docker inspect 容器id #查看容器的详细信息可以看到,docker容器id只是全部id前缀的部分截取
文件拷贝
1
2
3
4
5#将容器内的文件拷贝到容器外
docker cp 容器id:/home/Test.java /home
#将容器外的文件拷贝到容器内一般使用挂载盘符的方法实现
#只是简单修改的话还是可以直接拷贝,或者直接
docker cp /home/Test.java 容器id:/home
常用命令图解:
常见问题解决
后台启动自动停止
1
2docker run -d centOS
#后台运行后发现容器自动停止了原因:
后台运行docker容器必须指定前台进程,否则docker发现自己没有提供服务就会自动停止
查看日志
1
docker logs -f -t --tail 100 容器名或id
可视化
portainer
1 | docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock --restart=always --name portainer --privileged=true portainer/portainer |
在开放对应的端口号之后就可以通过外部访问
自定义镜像
容器数据卷
1 | docker volume ls #查看本地所有卷 |
如果数据保存在容器中,如果删除容器,数据也就会丢失,容器之间可以有一种数据共享的技术,Docker容器中产生的数据会同步到本地
卷技术:将容器内部的目录挂载到外部linux目录上,进行数据同步
目的:容器的持久化和同步操作,容器之间可以进行数据共享
直接使用命令挂载
1 | docker run -it -v 主机目录:容器内目录 镜像名 |
示例
1 | docker run -it -v ~/test:/home centos |
使用inspect命令查看详细信息
可以看到已经成功进行挂载,并且两边的文件夹已进行双向绑定,实际上是类似于硬链接的映射关系
具名和匿名挂载
其实就是挂载路径的体现方式
1 | -v 容器内路径 #匿名挂载 |
使用docker volume ls
查看所有卷
- 匿名挂载和指定路径挂在的卷名会自动生成
- 匿名挂载和具名挂载的默认主机挂载点为
/var/lib/docker/volumes/xxx/_data
读写权限
通过给-v
属性最后添加:ro或:rw来限制容器内部的读写权限
1 | docker run -it -v 主机目录:容器内目录:ro 镜像名 #容器内部目录只读权限 |
通过DockerFile挂载
编写用来构建docker镜像的脚本文件
注意左侧的命令大写,右侧的属性可以大小写
dockerfile01
1 | RROM centos |
利用Dockerfile构建容器并挂载
1 | docker build -f ~dockerFile01 -t newVolumeCentos:1.0 . #注意最后有'.' |
数据卷容器
多个容器同步数据
先创建docker01容器,这里的
newVolumeCentos:1.0
是之前创建的自定义镜像1
docker run -it --name docker02 newVolumeCentos:1.0
使用
--volumes-from
属性指定挂载的容器1
docker run -it --name docker02 --volume-from docker01 #之后docker01与docker02两个容器中的指定文件夹就进行了绑定
Dockerfile
构建自定义镜像的指令集合文件,默认名Dockerfile
,如果在当前目录中编写了这个文件,构建镜像时就不需要-f
指定Dockerfile文件
Dockerfile指令功能
指令必须大写,参数可以大小写
我们还可以使用docker history 镜像名
命令来查看镜像构建历史
CMD和ENTRYPOINT的区别
CMD:不能追加命令,如:
DockFile中编写
CMD ["ls","-a"]
执行时
docker run mycentos -l
会报错ENTRYPOINT:可以追加命令
与CMD不同,上面例子中的
docker run mycentos -l
可以正确执行
Dockerfile示例
docker原生的centos镜像删减了许多功能,例如:
- 没有设定工作目录,进入后默认在
\
路径 - ifconfig不能使用
- vim不能使用
我们可以对原生的centos镜像进行增强,使得上面这些功能可以使用
先编写自己的Dockerfile
myDockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14FROM centos
MAINTAINER lan5th<lan5th@foxmail.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---finish build---"
CMD "/bin/bash"构建镜像
1
docker build -f myDockerfile -t mycentos:0.1 .
进入镜像
1
docker run -it mycentos:0.1
发布镜像
发布镜像到DockerHub
登录
1 | docker login -u 用户名 #推荐执行之后再输入密码 |
1 | docker push lan5th/mycentos:0.1 #发布镜像 |
注意:镜像名一般需要改为用户名/镜像名
的格式
更改镜像名
1 | docker tag mycentos:0.1 lan5th/mycentos:0.1 |
发布镜像到阿里云镜像仓库
- 进入阿里云容器镜像产品
- 创建个人实例并进入
- 创建命名空间
- 创建容器镜像
- 根据官方文档的操作进行镜像操作
Docker网络
veth-pair
成对的虚拟设备接口,充当着桥梁的身份,连接各种虚拟网络设备
当我们启动docker容器时,docker会为容器自动分配ip地址,并且每次启动分配到的ip地址可能不同
当我们启动两个centos容器时(使用ip addr
查看网卡)
主机所有网卡
1:本机网卡
2:阿里云网卡
3:docker默认网卡
41:centos-01网卡的主机接口
43:centos-02网卡的主机接口
centos-01所有网卡
1:主机网卡
40:centos-01网卡的容器接口
centos-02所有网卡
1:主机网卡
42:centos-02网卡的容器接口
veth-pair桥接网卡图解:
无需配置ip地址的网络交互
由于ip地址是docker自动分配的,当我们操作具体业务时不可能每次部署都要手动配置ip地址
解决方法:
方式一:运行镜像时添加
--link
1
docker run -d -P --name centos-02 --link centos-01 centos
这种方式只能从centos-02连通centos-01,反之则不行
方式二:自定义网络
网络模式
- bridge:桥接模式,一般自定义网络也使用桥接模式
- none:不配置网络
- host:和主机共享网络
- container:容器网络连通(局限大,使用少)
1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
使用
docker network ls
查看,发现我们的自定义网络已经创建成功以自定义网络创建新镜像
1
2docker run -it -P --name centos-01 --net mynet centos
docker run -it -P --name centos-02 --net mynet centos从centos-01使用ping命令测试与centos-02的连接
说明我们的自定义网络已经能够实现我们的目标
之前的配置能够实现同一网段中使用容器name互联,那么如何使网段之间也能实现相同的功能?
网络连通
网段之间直接连通是不现实的,但我们可以将容器与其他网段的网络进行连通
1 | docker network connect 网络名 容器名 #连通指定网络和容器 |
相当于在指定网络和容器之间有新添加了一个网卡,之后就可以跨网段使用容器name进行互联
实战:部署SpringBoot项目
maven package打包成jar包
编写Dockerfile文件
1
2
3
4
5
6
7
8
9FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]把这两个文件发送到服务器上
构建镜像
1
docker build -t myspringboot .
运行镜像
1
docker run -d -P --name lan5th-springboot-web myspringboot
查看容器运行端口
docker ps
进行测试
curl localhost:49155/hello