Docker详解
什么是docker?
Docker 是一个应用打包、分发、部署的工具
你也可以把它理解为一个轻量的虚拟机,它只虚拟你软件需要的运行环境,多余的一点都不要,
而普通虚拟机则是一个完整而庞大的系统,包含各种不管你要不要的软件。
打包:就是把你软件运行所需的依赖,第三方库,软件打包打包在一起,
分发:你可以把你打包好的"安装包"上传到一个镜像仓库,其他人可以非常方便饿获取和安装
部署:拿着"安装包"就可以一个命令运行起来你的应用,自动模拟出和你一模一样的环境,不管在windows,linux,mac
docker的优势
优点:确保了不同机器上跑都是一致的运行环境,不会出现我机器上跑正常,你机器跑就有问题的情况。
Docker通常用来做什么
- 应用分发、部署,方便传播给他人安装。特别是开源软件和提供私有部署的应用
- 快速安装测试/学习软件,用完就丢(类似小程序),不把时间浪费在安装软件上。例如 Redis / MongoDB / ElasticSearch / ELK
- 多个版本软件共存,不污染系统,例如 Python2、Python3,Redis4.0,Redis5.0
- Windows 上体验/学习各种 Linux 系统
跟普通虚拟机的对比
特性 | 普通虚拟机 | Docker |
---|---|---|
跨平台 | 通常只能在桌面级系统运行,例如 Windows/Mac,无法在不带图形界面的服务器上运行 | 支持的系统非常多,各类 windows 和 Linux 都支持 |
性能 | 性能损耗大,内存占用高,因为是把整个完整系统都虚拟出来了 | 性能好,只虚拟软件所需运行环境,最大化减少没用的配置 |
自动化 | 需要手动安装所有东西 | 一个命令就可以自动部署好所需环境 |
稳定性 | 稳定性不高,不同系统差异大 | 稳定性好,不同系统都一样部署方式 |
docker内重要的概念
1-镜像:可以理解为软件的安装包,可以方便的进行传播和安装,镜像就是文件(而且镜像是只读文件),镜像只有一些针对文件的操作:获取,列举,查找,删除,创建
查看所有的镜像:
docker images
解释说明:第一列是镜像名称,第二列是tag,第三列式镜像id,类似于git中的提交时的sha值,可以用于运行镜像生成容器
我们还可以查询从docker官方库中的查找镜像,不是在本地查找镜像
docker search xxxxx
我们还可以删除镜像.只有在镜像里没有关联的容器才可以删除
docker rmi xxxxx
2-容器:软件安装后的状态,每个软件运行环境都是独立的,隔离的,称之为容器(容器不是真实存在一个容器存放东西,而是通过一些代码和技术实现的产物,所以大部分操作其实还是在宿主机的docker上操作的,并不是在容器里操作的).
容器不是文件或者文件夹,没有对应的目录. 可以理解为开启了一个镜像对应的进程.
镜像和容器的区别类似于代码和进程。
镜像是我们写的代码,而容器则是运行这个代码发起的进程。
所以镜像以文件形式保存在硬盘中,可以独立存在。而容器是个进程,只能靠运行镜像而存在,没有能够脱离于镜像而存在的容器。
一份代码可以执行多次产生多个进程,而一个进程只能由确定的一份代码产生。同样的从一个镜像可以发起多个容器,而一个容器肯定只能从一个镜像产生。
windows安装地址
桌面版:https://www.docker.com/products/docker-desktop
服务器版:https://docs.docker.com/engine/install/#server
镜像加速源
镜像加速器 | 镜像加速器地址 |
---|---|
Docker 中国官方镜像 | https://registry.docker-cn.com |
DaoCloud 镜像站 | http://f1361db2.m.daocloud.io |
Azure 中国镜像 | https://dockerhub.azk8s.cn |
科大镜像站 | https://docker.mirrors.ustc.edu.cn |
阿里云 | https://ud6340vz.mirror.aliyuncs.com |
七牛云 | https://reg-mirror.qiniu.com |
网易云 | https://hub-mirror.c.163.com |
腾讯云 | https://mirror.ccs.tencentyun.com |
例如:阿里云镜像加速配置(linux上docker已安装好的情况)
etc/docker/daemon.json文件并修改,如果没有这个文件,就新建touch daemon.json
{
"registry-mirrors": ["https://78q96cy9.mirror.aliyuncs.com"]
}
输入以下代码重启镜像、重启docker
systemctl daemon-reload 重新加载命令
systemctl restart docker 重新启动docker
在centos7上安装docker
一 Uninstall old versions(卸载旧的docker版本)
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
二 下载关于Docker的依赖环境
yum -y install yum-utils device-mapper-persistent-datalvm2
三 设置一下下载Docker的镜像源(如果不设置,会默认去Docker的官方下载)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
四 将软件包信息 提前在本地缓存一份 ,用来提高搜索安装软件的速度
yum makecache fast
五 安装docker相关的。(docker-ce 社区版 而ee是企业版)
yum -y install docker-ce docker-ce-cli containerd.io
启动DOCKER后的操作
启动docker
systemctl start docker
开启自动启动
systemctl enable docker
测试docker环境
docker run hello-world
查看hello-world镜像是否下载成功:docker images
Docker默认的工作路径是/var/lib/docker
常用命令
-
搜索镜像:docker search hello-world
-
拉取镜像:docker pull hello-world,默认情况下,会拉取最新版本镜像,如果需要拉取指定版本,则必须指定TAG标签。
-
运行镜像:docker run hello-world
-
查看镜像:docker images
-
查看容器:docker ps, docker container ls -a
-
启停容器:docker start/stop/restart hello-world(容器名)|容器id
-
删除容器:docker rm 容器名 (可通过container ls -a查看)
-
批量删除:docker rm $(docker ps -a -q)
-
删除镜像:docker rmi hello-world(id|name)
-
查看docker信息:docker inf
-
查看docker版本:docker -v
-
查看docker状态:systemctl status docker
-
下载命令补全工具:yum -y install bash-completion
-
docker volume ls
查看 volume 列表 -
docker network ls
查看网络列表 -
docker ps -l 查看最新创建的容器
-
容器详情 docker inspect id|name
-
查看容器进程 docker top
-
查看你容器日记 docker logs id|name
- -f :实时日记
- -t : 显示时间
- -tail: 控制输出行数
-
容器导入导出
- docker export -o 文件名.tar 容器id
-
将文件导入为镜像
- docker import 文件名.tar 镜像名:镜像标签
-
docker images
- TAG: TAG用于区分同一仓库中的不同镜像,默认为latest。
- IMAGE ID: IMAGE ID是镜像的一个唯一标识符。
- CREATED: CREATED表示镜像的创建时间。
- SIZE: SIZE表示镜像的大小。
docker上安装tomcat
方式1:(三部操作 docker pull docker create docker start)
1-从docker镜像源去拉取想要安装的tomcat到本地
docker pull tomcat:8.5.73 (指定版本)
查看拉取的容器
注意:如果不指定版本,会拉取镜像源上新版的tomcat到本地
2-下载好tomcat镜像后可以在镜像里创建tomcat容器
docker create --name tomcat1 tomcat #只创建不运行(先有镜像,才可以创建容器,通过tomcat镜像创建名称为tomcat1的容器)
查看创建的容器
3-运行容器
docker start CONTAINER ID
docker start d6a 表示运行了名称为tomcat1的容器
如果正要去在这种情况下去做端口映射,按下面的操作(不推荐,太麻烦))
在docker容器创建之后,想要增加端口映射,一般来说都是将原有的容器导出为镜像,然后删除原有容器,在重新创建的时候增加端口映射,但是这样操作起来太过于麻烦了。
现在有的办法也就是修改容器的配置文件。
主要有两个文件,一个hostconfig.json,一个config.v2.json.
路径主要是在/var/lib/docker/containers下。
1.首先将所有的容器都停止,docker stop {container_id/name} 有多少个就执行多少个,否则后面修改的配置文件会不生效,并且记住你要停止的docker容器的id的前几位(3-5位即可)
2.所有容器都停止之后,停止docker,systemctl stop docker
3.进入到/var/lib/docker/containers/{container_id}/ ,然后将hostconfig.json,config.v2.json做个备份,
接着就是来修改了。
这里可以看到有两个json文件:
hostconfig.json—— 配置宿主机和docker容器的端口映射关系
在 hostconfig.json 里有 “PortBindings”:{} 这个配置项,可以改成 “PortBindings”:{“80/tcp”:[{“HostIp”:"",“HostPort”:“8080”}], =“3306/tcp”:[{“HostIp”:"",“HostPort”:“3506”}]= }, 黄色部分为增加内容,这里 3306 是容器端口, 3506是宿主机端口;
在 config.v2.json 里面 “ExposedPorts”:{“3306/tcp”:{},“80/tcp”:{}},“Tty”:true 容器已经开启了3306端口,不用增加;
方式二(ctreate方式去映射端口)
1-从docker镜像源去拉取想要安装的tomcat到本地
docker pull tomcat:8.5.73 (指定版本)
查看拉取的容器
注意:如果不指定版本,会拉取镜像源上新版的tomcat到本地
2-直接create+端口映射
如果已存在这个容器,先停止运行这个容器,再删除.如果不存在,就直接操作
docker stop CONTAINER ID
docker rm 容器名 (可通过docker ps -a查看)
docker create --name tomcat1 -p 6060:8080 -v /usr/local:/usr/local/tomcat/webapps tomcat:8.5.73
- -d: 后台运行容器,并返回容器ID;
- -i: 以交互模式运行容器,通常与 -t 同时使用;
- -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
- --name tomcat1(注意:tomcat1只是容器的名字,并不是容器内也有一个tomcat1的tomcat文件,容器内的tomcat还是叫tomcat文件)
- -p(小写的p):是指定端口 (-P[大写的p]是指定随机端口)
- -p 6060:8080 :把tomcat容器的8080端口映射到宿主机的6060端口
- -v(小写的v):是指定挂载的目录
- -v /usr/local:/usr/local/tomcat/webapps:把tomcat容器内的/usr/local/tomcat/webapps目录映射到宿主机的/usr/local目录
tomcat:8.5.73
:是指镜像
小结:上面这句话就是指通过镜像创建了一个容器,并把这个容器端口映射到宿主机的端口,并把这个容器进行了挂载
如果启动或运行时遇见问题:查看日志
docker logs -f 容器id
docker端口挂载:
宿主机端口:docker容器的端口(容器端口映射到宿主机端口)
docker目录挂载
宿主机目录:docker容器目录(容器目录映射到宿主机目录)
使用xftp来查看docker 的目录 ,镜像和容器的目录信息
3-运行容器
root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6549bf0e4cd6 tomcat:8.5.73 "catalina.sh run" 2 minutes ago Created tomcat1
[root@localhost ~]# docker start 654
654
去浏览器测试 出现以下,表示tomcat:8.5.73容器创建成功(如果访问不了,注意关闭防火墙)
systemctl status firewalld
systemctl stop firewalld
进入容器:
docker exec -it 8b3 /bin/bas (容器运行了才可以进入)
将文件通过xftp传到/usr/local 目录下(这个目录是刚才挂载到宿主机的目录对应的的tomcat1容器的目录是 /usr/local/tomcat/webapps
)
方式三:一步搞定,直接通过run 的方式
docker run -id --name tomcat1 -p 6060:8080 -v /usr/local:/usr/local/tomcat/webapps tomcat:所要下载的镜像的版本号(也可以是镜像地址)
DOCKER组成
docker中有三个基本概念:
镜像(image):一个只读的模板,可以用来创建Docker容器。类似于Student类
容器(Container):容器是镜像创建的运行实例。容器是镜像运行时的实体,为镜像提供了一个标准的和隔离的运行环境。它可以被启动、停止、删除,每个容器之间都是隔离的。类似于stu实例对象
仓库(repository):存放镜像文件的地方。比如maven仓库是存放jar包的地方。
docker run 的执行流程及原理
docker是一个client-server结构的系统,docker的守护进程运行在主机上。dockerServer接收到docker-client的命令,就会执行这个命令。
doker端口映射的原理是什么?
Docker会随机映射一个物理机的49000~49900之间的端口到内部容器开放的网络端口。我们可以指定想要映射的物理机端口,并且,在一个指定端口上只可以绑定一个容器(docker通过端口绑定主机系统的接口,允许非本地客户端访问容器内部运行的服务。为了简便的使得容器间通信,docker提供了这种连接机制)。docker的端口映射并不是在docker技术中实现的,而是通过宿主机的iptables来实现;通过控制网桥来做端口映射,类似路由器中设置路由端口映射。
修改docker端口 (映射宿主机和docker容器中的端口)
- 查询已运行的容器
- 停止docker服务
3.进入主机配置文件目录
cd /var/lib/docker/containers/51360d643a33* ##51360d643a33 --->容器id
- 修改配置文件
原先我的mysql 映射端口是3306 ,这里我将它修改为3307
vim hostconfig.json
- 如果是修改docker 中的端口的话还需要执行下面这一步操作
vim config.v2.json
项目部署
1-创建并运行mysql容器
docker run -itd --name mysql -p 3306:3306 -v /opt/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=sq registry.cn-hangzhou.aliyuncs.com/sqqdcl/db:v6
如果命令需要换行使用\来分割
2-创建并运行rabbitmq容器(多个端口是开放web端)
docker run -itd --name rabbitmq -p 5672:5672 -p 15672:15672 -p 15692:15692 -v /opt/rabbitmq/data:/var/lib/rabbitmq -e RABBITMQ_DEFAULT_USER=guest -e RABBITMQ_DEFAULT_PASS=guest rabbitmq:3.8.3-management
3-创建并运行redis容器
-v /etc/localtime:/etc/localtime:ro
(数据存储库的时序挂载,这样时间就和宿主机同步了)
docker run -id --name redis -p 6379:6379 -v /opt/redis/data:/data -v /etc/localtime:/etc/localtime:ro registry.cn-hangzhou.aliyuncs.com/sqqdcl/redis
4-创建并运行秒杀系统的容器())
docker run -id --name miaosha -p 7080:7080 --link mysql --link rabbitmq --link redis:myRedis -v /etc/localtime:/etc/localtime:ro registry.cn-hangzhou.aliyuncs.com/sqqdcl/miaosha:3.0
访问秒杀系统:http://192.168.150.133:7080/
Dockerfile
Dockerfile是用来构建docker镜像的构建文件。
其实Dockerfile就是一个普通的文本文件,其中包含了一条条的指令,每一条指令都会构建一层。
dockerfile指令
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名+邮箱
RUN #镜像构建时需要运行的命令
ADD #步骤,tomcat镜像,这个tomcat压缩包;添加内容
WORKDIR #镜像工作目录
VOLUME #挂载的目录
EXPOSE #暴露端口配置
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD #当构建一个被继承DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY #类似ADD,将我们的文件拷贝至镜像中
ENV #构建的时候设置环境变量
FROM nginx 表示该镜像的构建,以已有的 nginx 镜像为基础,在该镜像的基础上构建。
MAINTAINER 指令用来声明创建镜像的作者信息以及邮箱信息,这个命令不是必须的。
RUN 指令用来修改镜像,算是使用比较频繁的一个指令了,该指令可以用来安装程序、安装库以及配置应用程序等,一个 RUN 指令执行会在当前镜像的基础上创建一个新的镜像层,接下来的指令将在这个新的镜像层上执行,RUN 语句有两种不同的形式:shell 格式和 exec 格式。本案例采用的 shell 格式,shell 格式就像 linux 命令一样,exec 格式则是一个 JSON 数组,将命令放到数组中即可。在使用 RUN 命令时,适当的时候可以将多个 RUN 命令合并成一个,这样可以避免在创建镜像时创建过多的层。
命令解释:
- -t 参数用来指定镜像的命名空间,仓库名以及 TAG 等信息。
- 最后面的
.
是指镜像构建上下文。
docker数据卷操作
一般情况下,当我们需要将数据从宿主机拷贝到容器中使用的都是docker的拷贝命令。数据卷可以避免这种麻烦的操作。
数据卷可以实现容器和宿主机之间的数据共享,简单来说数据卷就是在宿主机和容器之间搭建的一个映射的工作区,两者可以同步修改。
docker run -itd --name nginx -v /Users/sang/blog/docker/docker/:/usr/share/nginx/html/ -p 80:80 bc26f1ed35cf
这样便是将宿主机中的 /Users/sang/blog/docker/docker/ 目录挂载到容器的 /usr/share/nginx/html/ 目录下。接下来读者只需要在 /Users/sang/blog/docker/docker/ 目录下添加 html 文件,或者修改 html 文件,都能在 nginx 访问中立马看到效果。
查看所有的数据卷:
docker volume ls
查看数据卷详情
docker volume inspect
删除数据卷
docker volume rm
容器的Copy-on-Write特性
容器层
当容器启动时,一个新的可写层被加载到镜像的顶部,这一层被称为容器层
所有对容器的改动都发生在容器层
容器层的工作细节
- 添加文件:在容器中创建文件时,新文件会添加到容器层中
- 读取文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就打开并读入内存
- 修改文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就复制该文件到容器层,然后修改
- 删除文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就在容器层记录下删除的操作
只有当需要修改时,才复制一份数据,这个操作称为Copy-on-Write
总结:容器层保存的是镜像修改的部分,不会对镜像本身进行任何操作.
因此所有的镜像都是可读的,不会被容器修改,也因此镜像可以被多个容器共享
小技巧:
服务器上运行了多个容器,如何通过进程PID查找该进程是在哪个容器里面呢
ps -ef
ps -ef |grep 进程id