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

1684113053865

解释说明:第一列是镜像名称,第二列是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

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: 控制输出行数
  • 容器导入导出

    1. docker export -o 文件名.tar 容器id
    2. 将文件导入为镜像

    3. 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 (指定版本)

查看拉取的容器

1684115946387

注意:如果不指定版本,会拉取镜像源上新版的tomcat到本地

2-下载好tomcat镜像后可以在镜像里创建tomcat容器

docker create --name tomcat1 tomcat #只创建不运行(先有镜像,才可以创建容器,通过tomcat镜像创建名称为tomcat1的容器)

查看创建的容器

1684115970864

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 (指定版本)

查看拉取的容器

1684115946387

注意:如果不指定版本,会拉取镜像源上新版的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:是指镜像

小结:上面这句话就是指通过镜像创建了一个容器,并把这个容器端口映射到宿主机的端口,并把这个容器进行了挂载

如果启动或运行时遇见问题:查看日志

1684139830748

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

1684120403367

进入容器:

1684120707876

docker exec -it 8b3 /bin/bas (容器运行了才可以进入)

将文件通过xftp传到/usr/local 目录下(这个目录是刚才挂载到宿主机的目录对应的的tomcat1容器的目录是 /usr/local/tomcat/webapps)

1684121106538

1684121152269

方式三:一步搞定,直接通过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包的地方。

1684150072098

docker run 的执行流程及原理

1684150197406

docker是一个client-server结构的系统,docker的守护进程运行在主机上。dockerServer接收到docker-client的命令,就会执行这个命令。

1684150274446

doker端口映射的原理是什么?

Docker会随机映射一个物理机的49000~49900之间的端口到内部容器开放的网络端口。我们可以指定想要映射的物理机端口,并且,在一个指定端口上只可以绑定一个容器(docker通过端口绑定主机系统的接口,允许非本地客户端访问容器内部运行的服务。为了简便的使得容器间通信,docker提供了这种连接机制)。docker的端口映射并不是在docker技术中实现的,而是通过宿主机的iptables来实现;通过控制网桥来做端口映射,类似路由器中设置路由端口映射。

修改docker端口 (映射宿主机和docker容器中的端口)

  1. 查询已运行的容器
  2. 停止docker服务

3.进入主机配置文件目录

cd /var/lib/docker/containers/51360d643a33* ##51360d643a33 --->容器id

  1. 修改配置文件

原先我的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 命令合并成一个,这样可以避免在创建镜像时创建过多的层。

命令解释:

  1. -t 参数用来指定镜像的命名空间,仓库名以及 TAG 等信息。
  2. 最后面的 . 是指镜像构建上下文。

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特性

容器层

当容器启动时,一个新的可写层被加载到镜像的顶部,这一层被称为容器层

所有对容器的改动都发生在容器层

容器层的工作细节

  1. 添加文件:在容器中创建文件时,新文件会添加到容器层中
  2. 读取文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就打开并读入内存
  3. 修改文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就复制该文件到容器层,然后修改
  4. 删除文件:docker会从上往下,依次在各个镜像的层中查找文件,一旦找到就在容器层记录下删除的操作

只有当需要修改时,才复制一份数据,这个操作称为Copy-on-Write

总结:容器层保存的是镜像修改的部分,不会对镜像本身进行任何操作.

因此所有的镜像都是可读的,不会被容器修改,也因此镜像可以被多个容器共享

小技巧:

服务器上运行了多个容器,如何通过进程PID查找该进程是在哪个容器里面呢

ps -ef

ps -ef |grep 进程id

posted @ 2023-05-15 19:46  姜旭凌  阅读(182)  评论(2编辑  收藏  举报