目录
初识Docker
安装Docker
使用Docker
使用数据卷
使用Dockerfile
初识Docker
Docker概念:是一个开源的容器化平台,用于开发、打包和分发应用程序,通过Docker开发者可以将应用程序及其所有依赖(包括库、配置文件、系统工具等)打包成一个容器(容器之间使用沙箱机制相互隔离)确保应用在任何环境中都能一致地运行,解决了 “在我电脑上能运行,但在别人的电脑上却无法运行” 的问题,也就是我们常说的 “水土不服” 问题。
Docker是用Go语言开发的,所以具有高效的并发性和优越的性能,非常适合开发像Docker这样的分布式系统,其官网:地址 如下所示,详细文档参考:地址 ,并且它也有一个类似github的远程仓库:地址 里面有非常多的开源镜像,我们可以将其git pull拉取到本地也可以git push推送自己的镜像到仓库中:
Docker历史:Docker的历史可以追溯到2013年,它作为一种容器化技术迅速发展并改变了开发和部署应用的方式,以下是Docker的一些重要历史事件和发展历程:
1)起源DotCloud(2010年):
最初来源于一个名为DotCloud的公司,DotCloud的创始人Solomon Hykes发现现有的虚拟化技术存在很多限制特别是在容器化和自动化部署方面,他意识到需要一种更高效、更轻量的解决方案
2)Docker的诞生(2013年):
2013年3月Docker项目正式推出并且与DotCloud公司分开,Docker是由Solomon Hykes和团队开发的基于Linux容器(LXC)技术
3)Docker的开源和社区化(2013年):
docker从一开始就选择开源并迅速吸引了全球开发者的参与,开源意味着开发者可以自由使用修改和分发Docker促使其快速成长
4)容器化技术的普及(2015年以后):
越来越多的公司开始采用Docker来实现应用的容器化,Docker变得不仅仅是开发人员的工具也成为了运维、CI/CD(持续集成与持续交付)和微服务架构的核心技术
5)Docker的现代化(2019年以后):
2019年Docker公司宣布将焦点更多转向为开发者提供工具,特别是Docker Desktop和Docker Compose等工具,帮助开发者更高效地构建和管理容器化应用
比较Docker和虚拟机技术的不同:传统虚拟机虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件;容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的也没有虚拟我们的硬件所以就轻便了。
Docker架构:可以从三个核心部分来讲解:Clients(客户端)、Hosts(主机)、和Registries(镜像仓库)这三部分一起构成了Docker的整体架构,如下图所示:
1)Clients(客户端):客户端通常是用户通过命令行(CLI)或者图形界面(GUI)来使用Docker的方式,客户端可以直接运行在用户的本地机器上也可以远程连接到Docker引擎
2)Hosts(主机):指的是运行Docker引擎的机器,在主机上Docker引擎负责管理所有的容器和镜像,Docker主机可以是物理机器也可以是虚拟机
3)Registries(镜像仓库):用于存储和管理Docker镜像的地方,Docker镜像通常被存储在仓库中用户可以从仓库中拉取镜像也可以将自己创建的镜像推送到仓库
这里简单介绍一下Hosts主机的主要组件:
1)Docker Daemon(守护进程):这是Docker引擎的核心部分,负责接收来自客户端的请求并执行操作如创建、启动和停止容器、构建和管理镜像等
2)容器(Containers):容器是由Docker引擎创建并运行的应用程序实例,每个容器都基于Docker镜像并且在容器的文件系统内运行一个应用
3)镜像(Images):镜像是容器的只读模板,包含了应用程序及其所有运行时环境(操作系统、库、依赖等),Docker守护进程从镜像创建并运行容器
4)Docker网络和数据卷 (Volumes):Docker提供了网络配置和数据卷管理的功能以便容器之间可以互相通信并在容器之间共享数据
安装Docker
Docker可以运行在MAC、Windows、CentOS、UBUNTU等操作系统上,我们可以通过命令行界面(CLI)来实现用户与Docker进行交互,当然我们还可以使用Docker Desktop(桌面端Docker环境)来实现对Dcoker的操作,这里我们可以通过访问 文档 来了解安装及其下载需求:
下载安装:这里我们以windows环境安装Docker进行举例来讲解,点击如下安装链接进行安装,由于是国外的站点可能安装比较缓慢:
然后我们双击我们安装好的exe文件进行安装即可,安装完成然后点击重启电脑,重启完成之后点击接受协议即可完成:
然后接下来让我们选择设置,这里我们默认选择推荐设置即可:
然后到了下一步是让我们进行登录,这里我们选择继续不登录即可:
然后到了下一步问我们的角色是啥,这里我们还是跳过即可,至此我们的桌面端已经安装完成了:
中文汉化:安装好Docker Desktop不能切换语言,所以我们需要更改其脚本来实现汉化出来,打开如下的链接:地址 ,根据你下载的版本来找到对应的汉化文件:
然后将我们下载好的汉化文件,安装如下的路径重新命名app.asar,将原本的文件替换掉就可以了:
重新进入的话就会看到我们已经成功的对Docker Desktop进行汉化了:
WSL update failed:当我们运行Docker的时候可能会出现以下问题:
这里我们需要cmd执行如下命令进行wsl内核的更新:
wsl --update
安装完成之后我们的windos系统也会有linux系统的文件夹,通过适用于Linux的Windows子系统(WSL),可以直接在Windows上运行你最喜爱的Linux工具、实用工具、应用程序和工作流。
然后我们在使用账号登录桌面端,至此我们就可以愉快的使用Docker了:
相关配置:接下来对我们安装好的Docker桌面端进行一些相应的配置:
1)更换镜像位置:后期默认下载和设置的镜像我们将其位置弄到D盘
2)配置国内镜像源:由于默认镜像源是国外站点所以需要配置国内站点,完成下面配置后点击Apply & restart,能依旧看到engine running就OK了
"registry-mirrors":["https://docker.mirrors.ustc.edu.cn","https://registry.docker-cn.com","http://hub-mirror.c.163.com","https://mirror.ccs.tencentyun.com"
],
3)测试使用:我们打开cmd输入docker run hello-world来运行镜像,出现如下界面说明成功,该命令会从Docker Hub上拉取hello-world镜像并在容器中运行,该容器也会出现在我们的客户端中,也可以在客户端中运行,当然我们也可以在客户端中下载镜像:
当我们执行docker run的时候,其实会走以下流程,如果本地有镜像就使用,没有镜像就自动拉取远程仓库的镜像:
然后我们也能在桌面端中看到我们的镜像:
使用Docker
当我们安装好docker之后,接下来开始对docker进行操作使用了,一般我们安装好桌面端程序之后就不怎么需要熟练掌握命令行操作,但是这里还是简单的讲解一下:
1)查看docker版本,通过输入docker version进行查看:
2)docker常用命令,通过如下命令可以简单的执行操作docker
# 查看已下载的镜像:
docker images
# 查看正在运行的容器:
docker ps
# 查看所有容器(包括已停止):
docker ps -a
# 停止容器:
docker stop <容器ID或名称>
# 启动容器:
docker start <容器ID或名称>
# 删除容器:
docker rm <容器ID或名称>
# 删除镜像:
docker rmi <镜像ID或名称>
# 拉取镜像(例如:Nginx)
docker pull nginx
# 运行镜像(例如:Nginx)容器并映射端口:
docker run -d -p 8080:80 nginx
3)自定义镜像:我们可以通过创建Dockerfile文件,并将项目打包进行类似如下配置来创建自定义镜像:
# 使用官方的 Node.js 镜像作为基础
FROM node:18# 设置工作目录
WORKDIR /app# 复制当前目录下的所有文件到工作目录
COPY . /app# 安装项目依赖
RUN npm install# 暴露应用运行的端口
EXPOSE 3000# 启动应用
CMD ["npm", "start"]
配置完上面的镜像文件之后,我们通过如下命令来构建镜像:-t表示镜像指定名称;.表示Dockerfile在当前目录:
docker build -t my-node-app .
构建完镜像之后我们开始运行我们的容器,将容器的3000端口映射到主机的3000端口:
docker run -d -p 3000:3000 my-node-app
具体命令的作用可以参考以下内容:
常用的docker命令如下所示,更多详细的请参考官方文档 :地址 :
docker run:
--name 为容器指定名称
-i 即使未连接,也要保持STDIN 开放
-t 分配伪 TTY
-d 后台运行容器并打印容器ID
--gpus GPU设备添加到容器中(“all”表示传递所有GPU)
-v 绑定安装卷
-p 将容器的端口发布到主机
--rm 当容器退出时自动删除容器及其关联的匿名卷
使用数据卷
数据卷:宿主机中的一个目录或文件,当容器目录和数据卷目录绑定后对方的修改会立即同步,一个数据卷可以被多个容器同时挂载,当然一个容器也可以被挂载多个数据卷。数据库的作用如下:
1)容器数据的持久化
2)外部机器和容器间接通信
3)容器之间数据交换
我们可以通过如下命令来对数据卷进行相应的操作:
# 创建数据卷
docker volume create my-volume# 在容器中使用数据卷,-v 宿主机目录(文件): 容器内目录(文件)
# -v my-volume:/data:将数据卷挂载到容器的/data目录
docker run -d -v my-volume:/data busybox# 查看数据卷列表
docker volume ls# 删除数据卷
docker volume rm my-volume
使用Dockerfile
Docker镜像:用于创建容器的模板,包含了操作系统、应用程序、库、依赖等所有需要的文件是Docker的核心概念之一。其镜像原理如下所示:
1)Docker镜像是由特殊的文件系统叠加而成
2)最底端是bootfs并使用宿主机的bootfs
3)第二层是root文件系统rootfs,称为baseimage,然后再往上可以叠加其他的镜像文件
4)统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角这样就隐藏了多层的存在,在用户的角度看来只存在一个文件系统。
5)一个镜像可以放在另一个镜像的上面,位于下面的镜像称为父镜像最底部的镜像成为基础镜像
6)当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器
思考一下:
1)Docker镜像本质是什么?
是一个分层文件系统
2)Docker中一个centos镜像为什么只有200MB而一个centos操作系统的iso文件要几个G?
centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs只有rootfs和其他镜像层
3)Docker中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
由于docker中镜像是分层的,tomcat虽然只有70多MB但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB
镜像制作:对于镜像的制作上面其实讲解过用Dockerfile来自定义镜像,这里对其做一个具体的补充,首先对于镜像制作主要有以下俩种方式::
1)容器转为镜像:通过如下命令将一个容器转为新的镜像:
docker commit 容器id 镜像名称:版本号
docker save -o 压缩文件名称 镜像名称:版本号
docker load -i 压缩文件名称
我们执行docker ps -a可以看到我本地是只有一个hello world的镜像文件的
然后我们通过docker commit将我们的hello world镜像重新复制成一个hello docker镜像,查看我们的镜像文件之后可以看到我们复制的docker镜像已经被重新生成了:
然后我们通过将我们复制的镜像进行一个压缩就可以将我们复制的镜像发给别人进行使用了:
docker save -o hello-docker.tar hello-docker:1.0.0
在windos系统下我们通过dir可以查看当前文件目录内容,可以看到我们压缩的文件已经生成了:
然后我们通过如下命令删除镜像之后再加载我们上面压缩好的镜像文件:
2)Dcokerfile操作:Dockerfile是一个文本文件且包含了一条条的指令,每一条指令构建一层基于基础镜像,最终构建出一个新的镜像。
对于开发人员可以为开发团队提供一个完全一致的开发环境;对于测试人员可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作;对于运维人员在部署时可以实现应用的无缝移植,我们可以在dockerhub仓库中可以随便找一个镜像,其对于的Dockerfile文件内容大致如下:
这里我罗列一下Dockerfile中常见的关键字及其作用:
关键字 | 作用 | 备注 |
---|---|---|
FROM | 指定父镜像 | 指定dockerfile基于那个image构建 |
MAINTAINER | 作者信息 | 用来标明这个dockerfile谁写的 |
LABEL | 标签 | 用来标明dockerfile的标签可以使用Label代替Maintainer最终都是在dockerimage基本信息中可以查看 |
RUN | 执行命令 | 执行一段命令默认是/bin/sh格式:RUNcommand或者RUN,["command","param1","param2"] |
CMD | 容器启动命令 | 提供启动容器时候的默认命令和ENTRYPOINT配合使用,格式CMD command param1param2或者CMD[command","param1","param2"] |
ENTRYPOINT | 入口 | 一般在制作一些执行就关闭的容器中会使用 |
COPY | 复制文件 | build的时候复制文件到image中 |
ADD | 添加文件 | build的时候添加文件到image中不仅仅局限于当前build上下文可以来源于远程服务 |
ENV | 环境变量 | 指定build时候的环境变量可以在启动的容器的时候通过-e覆盖格式ENV name=value |
ARG | 构建参数 | 构建参数只在构建的时候使用的参数如果有ENV那么ENV的相同名字的值始终覆盖arg的参数 |
VOLUME | 定义外部可以挂载的数据卷 | 指定build的image那些目录可以启动的时候挂载到文件系统中启动容器的时候使用-V绑定格式VOLUME["目录"] |
EXPOSE | 暴露端口 | 定义容器运行的时候监听的端口启动容器的使用-p来绑定暴露端口格式:EXPOSE8080或者EXPOSE8080/udp |
WORKDIR | 工作目录 | 指定容器内部的工作目录如果没有创建则自动创建如果指定/使用的是绝对地址如果不是/开头那么是在上一条workdir的路径的相对路径 |
USER | 指定执行用户 | 指定build或者启动的时候用户在RUNCMDENTRYPONT执行的时候的用户 |
HEALTHCHECK | 健康检查 | 指定监测当前容器的健康监测的命令基本上没用因为很多时候应用本身有健康监测机制 |
ONBUILD | 触发器 | 当存在ONBUILD关键字的镜像作为基础镜像的时候当执行FROM完成之后会执行ONBUILD的命令但是不影响当前镜像用处也不怎么大 |
STOPSIGNAL | 发送信号量到宿主机 | 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出 |
SHELL | 指定执行脚本的shell | 指定RUNCMDENTRYPOINT执行命令的时候使用的shell |
在项目中如果我们想使用Docker进行程序发布的话,我们可以右键项目然后点击添加,选择Docker支持,如下所示:
然后我们接下来开始选择容器基础框架的选项操作,如下所示:
1)容器OS:专门为运行容器优化的操作系统,专门为运行容器优化的操作系统
2)容器生成类型:构建容器的方式和方法,选择合适的构建类型能优化镜像大小、构建速度和可维护性
3)容器镜像SKU:容器镜像的不同配置版本,一个镜像可以有多个不同的SKU版本这些版本之间可能包含不同的库、应用或系统设置
4)Docker生成上下文:在构建Docker镜像时所需要的文件、目录及其他资源的集合,上下文中通常包含应用代码、配置文件、依赖文件等
点击确定之后就会在项目中生成一个Dockerfile文件,我们可以根据需要添加如下内容:
# 使用官方的 .NET Core SDK 镜像来构建应用
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app# 复制 csproj 并还原依赖
COPY *.csproj .
RUN dotnet restore# 复制所有文件并构建应用
COPY . .
RUN dotnet publish -c Release -o out# 使用运行时镜像来运行应用
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build /app/out .# 设置应用默认端口
ENV ASPNETCORE_URLS=http://+:80
EXPOSE 80# 启动应用
ENTRYPOINT ["dotnet", "webapi-study.dll"]
当然我们也可以在项目根目录中创建一个.dockerignore 文件以避免将不需要的文件复制到Docker镜像中,可以添加如下内容:
bin/
obj/
*.sln
*.user
然后我们在项目的根目录下,使用以下命令构建Docker镜像,t是指定镜像名,.是表示当前目录也就是Dockerfile文件所在的目录,如果是本地打包直接定位到文件目录,然后输入docker build就可以了:
docker build -t auth .
构建完成后,可以通过以下命令运行Docker容器,此命令会将容器的80端口映射到宿主机的5000端口,现在可以通过访问http://localhost:5000来访问Web API了:
docker run -d -p 5000:80 --restart=always --name mywebapi mywebapi
在运行应用时,如果需要检查容器的状态或停止它,可以通过如下命令进行操作:
# 查看正在运行的容器:
docker ps停止容器:
# docker stop mywebapi_container删除容器:
# docker rm mywebapi_container
当然如果我们本地安装了Docker的话,可以通过页面端进行操作: