文章目录前言Docker详解Docker简介docker和传统虚拟机区别Docker架构Docker安装检查系统信息更新依赖导入 Docker 官方密钥添加 Docker 源安装 Docker启动并加入开机启动配置国内镜像加速测试启动状态Docker 镜像指令镜像搜索拉取镜像查看本地镜像删除本地镜像Docker 容器指令启动容器查看容器信息停止容器强制停止容器启动已停止的容器查看指定容器所有信息查看容器日志查看容器里的进程宿主机与容器之间互相拷贝文件进入指定容器容器内安装vim、ping、ifconfig等指令删除容器Docker 挂载PV什么是 PV 挂载以Mysql为例1、创建宿主机持久化目录执行一次2、启动Mysql容器指令调整3、验证是否挂载成功原理说明Dockerfile 方式构建自定义镜像构建自定义nginx创建目录和文件使用指令构建镜像Dockerfile常用指令前言2013年发布至今 Docker 一直广受瞩目被认为可能会改变软件行业。但是许多人并不清楚 Docker 到底是什么要解决什么问题好处又在哪里今天就写一下博客记录下自己安装、配置和使用中出现的一些问题希望对铁子们有所帮助。Docker详解Docker简介Docker是一个开源的容器化平台可以帮助开发者将应用程序和其依赖的环境打包成一个可移植、可部署的容器。Docker的主要目标是通过容器化技术实现应用程序的快速部署、可移植性和可扩展性从而简化应用程序的开发、测试和部署过程。容器化是一种虚拟化技术它通过在操作系统层面隔离应用程序和其依赖的运行环境使得应用程序可以在一个独立的、封闭的环境中运行而不受底层操作系统和硬件的影响。与传统的虚拟机相比容器化具有以下优势轻量级: 容器与宿主机共享操作系统内核因此容器本身非常轻量级启动和停止速度快资源占用少。可移植性: 容器可以在任何支持相应容器运行时的系统上运行无需关注底层操作系统的差异提供了高度的可移植性。快速部署: 容器化应用程序可以通过简单的操作进行打包、分发和部署减少了部署过程的复杂性和时间成本。弹性扩展: 可以根据应用程序的需求快速创建、启动和停止容器实例实现应用程序的弹性扩展和负载均衡。环境隔离: 每个容器都具有独立的运行环境容器之间相互隔离不会相互干扰提供了更好的安全性和稳定性。docker和传统虚拟机区别虚拟机是一个主机模拟出多个主机需要先拥有独立的系统。传统虚拟机利用hypervisor模拟出独立的硬件和系统在此之上创建应用。docker 是在主机系统中建立多个应用及配套环境把应用及配套环境独立打包成一个单位是进程级的隔离。Docker架构Docker daemon Docker守护进程Docker daemon是一个运行在宿主机 DOCKER-HOST的后台进程。可通过 Docker客户端与之通信。Client Docker客户端Docker客户端是 Docker的用户界面它可以接受用户命令和配置标识并与 Docker daemon通信。图中 docker build等都是 Docker的相关命令。Images Docker镜像Docker镜像是一个只读模板它包含创建 Docker容器的说明。它和系统安装光盘有点像使用系统安装光盘可以安装系统同理使用Docker镜像可以运行 Docker镜像中的程序。Container容器容器是镜像的可运行实例。镜像和容器的关系有点类似于面向对象中类和对象的关系。可通过 Docker API或者 CLI命令来启停、移动、删除容器。RegistryDocker Registry是一个集中存储与分发镜像的服务。构建完 Docker镜像后就可在当前宿主机上运行。但如果想要在其他机器上运行这个镜像就需要手动复制。此时可借助 Docker Registry来避免镜像的手动复制。一个 Docker Registry可包含多个 Docker仓库每个仓库可包含多个镜像标签每个标签对应一个 Docker镜像。这跟 Maven的仓库有点类似如果把 Docker Registry比作 Maven仓库的话那么 Docker仓库就可理解为某jar包的路径而镜像标签则可理解为jar包的版本号。Docker Registry可分为公有Docker Registry和私有Docker Registry。 最常⽤的Docker Registry莫过于官方的Docker Hub 这也是默认的Docker Registry。 Docker Hub上存放着大量优秀的镜像 我们可使用Docker命令下载并使用。Docker安装本次使用的是腾讯云服务器系统为Ubuntu。Centos 相对好安装一点Ubuntu 系统没有相关的 yml 指令。安装参考阿里巴巴开源镜像站中的说明地址如下所示https://developer.aliyun.com/mirror/docker-ce?spma2c6h.13651102.0.0.5c611b11axETqq检查系统信息使用如下指令查看服务器的系统信息cat/etc/os-release监测到当前系统是Ubuntu使用 apt-get 进行安装。更新依赖aptupdateaptinstall-yca-certificatescurlgnupg lsb-release导入 Docker 官方密钥curl-fsSLhttps://download.docker.com/linux/ubuntu/gpg|gpg--dearmor-o/usr/share/keyrings/docker-archive-keyring.gpg添加 Docker 源echodeb [arch$(dpkg --print-architecture)signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu$(lsb_release-cs)stable|tee/etc/apt/sources.list.d/docker.list/dev/null安装 Dockeraptupdateaptinstall-ydocker-ce docker-ce-cli containerd.io docker-compose-plugin启动并加入开机启动systemctl startdockersystemctlenabledocker配置国内镜像加速登录阿里云的镜像加速器https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors如下图所示根据自己的系统选择对应的配置信息本次测试验证使用的是Ubuntu。将其全量复制到控制台中回车。mkdir-p/etc/dockertee/etc/docker/daemon.json-EOF { registry-mirrors: [https://l8jvnvev.mirror.aliyuncs.com] } EOF如果存在daemon.json文件则进行修改。vimdaemon.json{registry-mirrors:[https://jbw52uwf.mirror.aliyuncs.com]}【注意】阿里云的镜像加速器不可用了可以用下面的替代{registry-mirrors:[https://docker.1ms.run,https://hub.rat.dev,https://docker.1panel.live]}执行完成后重启Dockersystemctl daemon-reload systemctl restartdocker测试启动状态先拉取docker给出的测试实例dockerpull hello-world# 或者指定完整地址dockerpull docker.io/library/hello-world:latest查看当前docker的版本信息启动已经拉取的实例。dockerversiondockerrun hello-worldDocker 镜像指令镜像搜索可使用 docker search命令搜索存放在 Docker Hub中的镜像。执行该命令后 Docker就会在Docker Hub中搜索含有 java这个关键词的镜像仓库。docker search java【注意】但是目前在国内已经禁止访问Docker Hub这个指令可能会执行失败。如果执行成功控制台会输出如下信息找的图我的执行失败了。列表中的各项属性信息。属性名称NAMEDESCRIPTIONSTARSOFFICALAUTOMATED含义镜像仓库名称镜像仓库描述镜像仓库收藏数表示该镜像仓库的受欢迎程度类似于 GitHub的 stars0表示是否为官方仓库该列标记为[0K]的镜像均由各软件的官方项目组创建和维护表示是否是自动构建的镜像仓库拉取镜像使用Docker部署服务前需要先从中央镜像仓库中拉取镜像。本次以nginx为例。dockerpull nginx【提示】如果不指定版本直接拉取镜像默认会拉取最新的镜像信息。如果需要指定版本可以使用下面的方式dockerpull nginx:1.21查看本地镜像查看本地已经拉取过的所有镜像信息可以使用下面的指令dockerimages你会看到刚刚下载的所有镜像信息包括仓库名、标签(版本)、镜像ID、创建时间和大小。如果觉得数据很多只想看ID信息可以使用如下方式。dockerimages-q删除本地镜像使用docker提供的rmi指令进行指定镜像的删除如果需要强制删除可以追加一个-f。如下dockerrmijava强制删除dockerrmi-fjava【注意】如果有容器正在使用这个镜像必须先删除所有依赖该镜像的容器然后才能删除镜像。删除所有镜像dockerrmi$(dockerimages-q)Docker 容器指令以nginx为例nginx启动后自带默认的首页信息方便验证。启动容器拉取镜像成功后使用docker提供的启动命令进行镜像的部署操作。核心指令dockerrun-d-pxx:xx 镜像名比如上述拉取的是最新的nginx镜像启动时配置宿主机与镜像的端口映射等。dockerrun-d--namemy-nginx-demo-p80:80 nginx指令参数说明因为markdown语法问题指令之间为了区别多加了个空格。实际使用需要做区分指令名称含义举例原指令-d-detach 的缩写表示后台运行类似 nohoup-P随机端口映射一般不用-p指定端口映射。如果存在多个端口映射则调用多个一般分为4种方式- -ip:hostPort:containerPort- - ip::containerPort- - hostPort:containerPort- - containerPort-p 80:80- -net指定网络模式一般有4中模式- -netbridge默认选项表示连接到默认的网桥。- -nethost 容器使用宿主机的网络。- -netcontainer:NAME-or-ID 告诉 Docker让新建的容器使用已有容器的网络配置。- -netnone 不配置该容器的网络用户可自定义网络配置。–netbridge- -name指定别名称比如 - -name:my-nginx-demo–name:my-nginx-demo执行上述指令如下出现随机一串uuid表示成功。访问 http://Docker宿主机 IP:91/将会看到nginx的主界面如下如果别名称出现重复启动会出现报错。查看容器信息查看所有的已启动的容器列表可以使用下列指令dockerps如果需要展示所有已启动和未启动的容器列表需要增加一个-a指令。dockerps-a已成功启动的容器信息全部容器信息展示信息的各项列值说明列名CONTAINER_IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES含义容器 ID镜像名称启动容器时运行的命令容器的创建时间容器运行的状态。UP表示运行中 Exited表示已停止。容器对外的端口号容器名称。该名称默认由 Docker自动生成也可使用 docker run命令的–name选项自行指定。停止容器使用 docker stop命令即可停止容器dockerstop 容器id|容器名称比如上述的nginx容器对应的容器idCONTAINER ID为9ae51d610d4c则可以使用下列指令进行停止。dockerstop 9ae51d610d4c或者使用容器名称停止。dockerstop my-nginx-demo强制停止容器可使用 docker kill命令发送 SIGKILL信号来强制停止容器dockerkill9ae51d610d4c启动已停止的容器这里的启动操作与docker run有很大的区别docker run除了启动对应的容器外还包含新建容器等额外的操作。启动一个已停止的容器只需要使用docker start即可。dockerstart 容器id比如上面停止了nginx的容器需要启动则使用下列指令实现dockerstart 9ae51d610d4c查看指定容器所有信息dockerinspect 容器id查看容器日志dockercontainer logs 容器id查看容器里的进程dockertop容器id宿主机与容器之间互相拷贝文件互相复制文件需要分两种情况从容器里面拷文件到宿主机使用下列的指令实现dockercp容器id:要拷贝的文件在容器里面的路径 宿主机的相应路径比如dockercp9ae51d610d4c:/etc/nginx/nginx.conf /mydata/nginx从宿主机拷文件到容器里面dockercp要拷贝的宿主机文件路径 容器id:要拷贝到容器里面对应的路径进入指定容器使用docker exec命令用于进入一个正在运行的docker容器。如果docker run命令运行容器的时候没有使用-it参数就要用这个命令进入容器。一旦进入了容器就可以在容器的 Shell 执行命令了。dockerexec-it9ae51d610d4c /bin/sh这里指令中的-it含义如下1、-i全称--interactive。保持标准输入开启作用让你可以往容器里输入命令、打字不加-i进去之后没法输入字符只能看不能操作2、-t全称--tty分配一个伪终端作用给你一个像正常服务器一样的终端界面有命令行提示符、光标、格式排版不加-t界面很丑没有命令行前缀输入体验极差【注意】上述的指令中/bin/sh是Ubuntu操作系统的指令如果是Centos系统则需要使用/bin/bash。容器内安装vim、ping、ifconfig等指令容器内可能会存在linux指令不全的问题需要进行容器内的相关指令安装。即使宿主机是Centos进入容器后也像Ubuntu的操作指令。apt-getupdateapt-getinstallvim#安装vimapt-getinstalliputils-ping#安装pingapt-getinstallnet-tools#安装ifconfig【问】进入容器内的shell操作窗口后怎么退出容器操作输入 exit删除容器删除容器指令分为安全和强制两种情况。安全删除容器仅能删除已停止的容器。dockerrm9ae51d610d4c强制删除容器如果容器正在运行需要删除可以追加-f指令dockerrm-f9ae51d610d4c强制删除所有容器dockerrm-f$(dockerps-a-q)Docker 挂载PV为什么会有要求必须挂载PV的操作在实验过程中发现一个现象启动和停止容器时会创建和删除对应的目录信息。还是以nginx为例如下所示查看已启动的容器信息。dockerps执行指令后可以看到 docker 在/var/lib/docker/rootfs/overlayfs目录中会存留容器的相关目录信息。如果此时停止nginx的容器会发生什么dockerstop 9ae51d610d4c这里居然存储的信息被删除了如果再docker start操作则会继续重新创建目录。到这里就会有一个很严重的问题大家都知道Docker是可以部署Nginx、Mysql这些东西的如果容器不小心执行停止指令那么像nginx的/etc/nginx/conf.d/xxx相关配置会丢mysql的/var/lib/mysql/xxx这些存储文件都会丢失这是一个很严重的生产风险问题【疑惑】如何解决这个问题呢这里就要提到目录标题说到的PV挂载。什么是 PV 挂载在 Docker 里容器是临时的。容器删了里面的文件、数据、配置全都会跟着消失。如果你直接把 RabbitMQ 的队列数据、用户配置、日志都存在容器内部那下次重启或重建容器数据就丢了。把容器里需要持久化的数据目录映射到宿主机你的服务器上的一个真实目录让数据保存在宿主机上而不是容器里。以Mysql为例这里以Mysql的启动配置为例。在Mysql中通常有以下几个目录特别重要。宿主机目录 → 容器内目录 ---------------------------------------- /data/mysql/data → /var/lib/mysql 数据文件最重要 /data/mysql/conf → /etc/mysql/conf.d 配置文件 /data/mysql/logs → /var/log/mysql 日志1、创建宿主机持久化目录执行一次mkdir-p/data/mysql/{data,conf,logs}2、启动Mysql容器指令调整dockerrun-d\--namemysql\-p3306:3306\-v/data/mysql/data:/var/lib/mysql\-v/data/mysql/conf:/etc/mysql/conf.d\-v/data/mysql/logs:/var/log/mysql\-eMYSQL_ROOT_PASSWORD123456\-eTZAsia/Shanghai\--restartalways\mysql3、验证是否挂载成功首先先看容器中是否存在对应的数据/var/lib/mysql检查宿主机挂载目录是否存在数据cd /data/mysql/关闭Mysql容器查看是否会删除以及验证再次重启是否会读取。原理说明加了-v 宿主机目录:容器内目录挂载后启动时容器优先读宿主机这个目录里的配置 / 文件运行中容器产生的所有数据、日志、新增文件实时写到宿主机目录容器本身内部不再存数据数据全落在宿主机上步骤说明启动读取阶段Docker 启动容器时监测到创建容器指令中存在-v /宿主机路径:/容器路径会直接把容器里这个目录 “屏蔽替换” 成宿主机目录容器所有读写全部指向宿主机不碰容器内部存储。运行写入阶段容器里程序MySQL/Nginx/RabbitMQ往自身目录写数据容器内 /var/lib/mysql 写数据 ↓ 被挂载映射 ↓ 实际写到 宿主机 /data/mysql/data实时同步、即时写入不是缓存、不是定时同步是内核级目录映射。【注意】这里需要注意一点问题。nginx 的 pv 挂载操作宿主机挂载目录千万别一开始是空的直接挂因为容器在启动前会把容器默认配置覆盖掉导致启动失败对于类似 nginx 的正确处理方式如下先临时容器拷出默认配置再挂载Dockerfile 方式构建自定义镜像Dockerfile是一个文本文件其中包含了若干条指令指令描述了构建镜像的细节。在实际工作中这个用的比较普遍而且和K8S之间能很好地契合。接下来重点说明一下怎么玩。构建自定义nginx先来编写一个最简单的Dockerfile以前文下载的Nginx镜像为例来编写一个Dockerfile修改该Nginx镜像的首页。创建目录和文件如在linux系统中创建一个文件夹/root/my-docker。并在其中创建子目录。mkdir-p/myNginx/app在app文件夹中新增两个文件分别是Dockerfile文件和index.html。其中内容如下所示Dockerfile # 基础镜像FROM nginx:latest# 指定工作区间#workdir /root/nginx# 把本地 index.html 复制到容器里COPY index.html /usr/share/nginx/html/# 暴露端口EXPOSE80# 启动命令默认 nginx 不用改CMD[nginx,-g,daemon off;]index.html 页面!DOCTYPEhtmlhtmlheadmetacharsetUTF-8title/title/headbodyh1我用 Dockerfile 构建的 Nginx 镜像/h1/body/html使用指令构建镜像docker 提供了构建的指令。dockerbuild-fDockerfile文件名称-t镜像名称:版本.指令拆分解读。-t--tag指令的缩写用于给镜像指定别名称和版本信息。.最后还有个.不能省略这里指Dockerfile 文件的路径。目前测试时Dockerfile文件的完整路径是/root/my-docker/myNginx/app/Dockerfile。如果正好在/root/my-docker/myNginx/app/路径下执行命令案例如下dockerbuild-tmy-nginx:v2.如果是在/root/my-docker/下则需要调整命令如下所示dockerbuild-tmy-nginx:v2 ./myNginx/app/命令执行完成后控制台中输出如下信息查看构建的镜像信息。启动镜像Dockerfile常用指令下面列举几项常用指令。命令说明举例FROM指定基础镜像文件并拉取FROM nginx:latestRUN构建镜像阶段执行命令RUN mkdir -p /home/serverADD src dest添加文件从src目录复制文件到容器的dest其中 src可以是 Dockerfile所在目录的相对路径也可以是一个 URL,还可以是一个压缩包ADD fuxi/dist.tar.gz /usr/local/nginx/fuxi/COPY拷贝文件和ADD命令类似但不支持URL和压缩包COPY nginx-prod.conf /etc/nginx/conf.d/default.confCMD容器启动后执行命令EXPOSE声明容器在运行时对外提供的服务端口WORKDIR指定容器工作路径WORKDIR /home/serverENV指定环境变量ENV LC_ALL zh_CN.UTF-8ENTRYPINT容器入口 ENTRYPOINT和 CMD指令的目的一样都是指定 Docker容器启动时执行的命令可多次设置但只有最后一个有效。USER该指令用于设置启动镜像时的用户或者 UID,写在该指令后的 RUN、 CMD以及 ENTRYPOINT指令都将使用该用户执行命令。VOLUME指定挂载点该指令使容器中的一个目录具有持久化存储的功能该目录可被容器本身使用也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在 Dockerfile中使用该指令。格式为 VOLUME[“/data”]。