参考来源:
(应用的容器化实践)docker官方入门指南 https://docs.docker.com/get-started/
本指南包含有关如何开始使用 Docker 的分步说明。本指南介绍如何:
将映像作为容器生成并运行。
使用 Docker Hub 共享映像。
使用带有数据库的多个容器部署 Docker 应用程序。
使用 Docker Compose 运行应用程序。
step1 docker的基础概念
- Image(镜像)
- Container(容器)
- Repository(仓库)
镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,可见镜像更是 Docker 的核心。
什么是容器
容器是在主机上运行的沙盒进程,它与该主机上运行的所有其他进程隔离。这种隔离利用了内核命名空间和 cgroup,这些特性在 Linux 中已经存在了很长时间。Docker 使这些功能变得平易近人且易于使用。总而言之,容器:
是镜像的可运行实例。您可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。
可以在本地计算机、虚拟机上运行,也可以部署到云中。
是可移植的(可以在任何操作系统上运行)。
与其他容器隔离,并运行自己的软件、二进制文件、配置等。
容器(Container)的定义和镜像(Image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
由于容器的定义并没有提及是否要运行容器,所以实际上,容器 = 镜像 + 读写层。
什么是镜像
正在运行的容器使用隔离的文件系统。这个隔离的文件系统由映像提供,映像必须包含运行应用程序所需的一切——所有依赖项、配置、脚本、二进制文件等。该映像还包含容器的其他配置,例如环境变量、要运行的默认命令和其他元数据。
Image(镜像)
那么镜像到底是什么呢?Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。
镜像不包含任何动态数据,其内容在构建之后也不会被改变。
什么是仓库
Repository(仓库)
Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行。
但是, 如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry(仓库注册服务器)就是这样的服务。
有时候会把仓库(Repository)和仓库注册服务器(Registry)混为一谈,并不严格区分。
Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。
实际上,一个 Docker Registry 中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应着一个镜像。
所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。
我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 Latest 作为默认标签。
仓库又可以分为两种形式:
- Public(公有仓库)
- Private(私有仓库)
Docker Registry 公有仓库是开放给用户使用、允许用户管理镜像的 Registry 服务。
一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。
当用户创建了自己的镜像之后就可以使用 Push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 Pull 下来就可以了。
step2 容器化应用
接下来,您将容器化一个简单的应用程序,并亲身体验这些概念。
容器化应用程序
在本指南的其余部分,您将使用在 Node.js 上运行的简单待办事项列表管理器。如果您不熟悉Node.js,请不要担心。本指南不需要任何 JavaScript 经验。
先决条件: prerequistes
您已安装最新版本的 Docker Desktop。
您已安装 Git 客户端。
您必须使用 IDE 或文本编辑器来编辑文件。Docker 建议使用 Visual Studio Code。
获取应用程序
1.在运行应用程序之前,需要将应用程序源代码放到计算机上。
使用以下命令克隆 getting-started-app 存储库:
git clone https://github.com/docker/getting-started-app.git
2.查看克隆存储库的内容。您应该会看到以下文件和子目录。
root@ub1804:/home/xiaoyue/workdir/dockerdir/getting-started-app# tree -d
.
├── spec
│ ├── persistence
│ └── routes
└── src
├── persistence
├── routes
└── static
├── css
│ └── font-awesome
└── js
构建应用的镜像
1.在与 package.json 文件相同的 getting-started-app 目录中,创建一个名为 Dockerfile 的文件。您可以使用以下命令创建基于您的操作系统的 Dockerfile。
cd /path/to/getting-started-app
touch Dockerfile
- 使用文本编辑器或代码编辑器,将以下内容添加到 Dockerfile:
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
- 使用以下命令生成映像:
在终端中,确保您位于目录中 getting-started-app 。替换 /path/to/getting-started-app 为 getting-started-app 目录的路径。
生成映像。
#命令末尾的 . 告诉 Docker 它应该在当前目录中查找
docker build -t getting-started .
root@ub1804:/home/xiaoyue/workdir/dockerdir/getting-started-app# docker build -t getting-started .
Sending build context to Docker daemon 7.153MB
Step 1/6 : FROM node:18-alpine
---> 7f58449cc6fc
Step 2/6 : WORKDIR /app
---> Using cache
---> 24b4ab64ae6b
Step 3/6 : COPY . .
---> Using cache
---> 7a032ef2762e
Step 4/6 : RUN yarn install --production
---> Running in db2e64acc69e
yarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 85.98s.
Removing intermediate container db2e64acc69e
---> b24c0f38c084
Step 5/6 : CMD ["node", "src/index.js"]
---> Running in bd85eb6ffad6
Removing intermediate container bd85eb6ffad6
---> 07e3586acabc
Step 6/6 : EXPOSE 3000
---> Running in c90f4c4efb49
Removing intermediate container c90f4c4efb49
---> 340c53ee3972
Successfully built 340c53ee3972
Successfully tagged getting-started:latest
启动应用容器
现在,您已经有了映像,可以使用命令 docker run 在容器中运行应用程序
- 使用命令 docker run 运行容器,并指定刚刚创建的映像的名称:
docker run -dp 127.0.0.1:3000:3000 getting-started
- 几秒钟后,打开 Web 浏览器进行 http://localhost:3000。您应该会看到您的应用。
- 添加一两个项目,看看它是否按预期工作。您可以将项目标记为完成并移除它们。前端已成功将项目存储在后端。
此时,您有一个正在运行的待办事项列表管理器,其中包含一些项目。
总结:
在本部分中,你学习了有关创建 Dockerfile 以生成镜像的基础知识。生成镜像后,启动容器并看到正在运行的应用。
step3 更新程序
接下来,你将对应用进行修改,并了解如何使用新映像更新正在运行的应用程序。在此过程中,您将学习一些其他有用的命令。
在第 2 部分中,您容器化了一个待办事项应用程序。在本部分中,您将更新应用程序和映像。您还将学习如何停止和移除容器。
更新源代码
在以下步骤中,您需要将没有任何待办事项列表项时的“空文本”更改为“您还没有待办事项!在上面加一个!
- 在 src/static/js/app.js 文件中,更新第 56 行以使用新的空文本。
- <p className="text-center">No items yet! Add one above!</p>
+ <p className="text-center">You have no todo items yet! Add one above!</p>
2.使用命令 docker build 生成映像的更新版本。
root@ub1804:/home/xiaoyue/workdir/dockerdir/getting-started-app# docker build -t getting-started .
Sending build context to Docker daemon 7.153MB
Step 1/6 : FROM node:18-alpine
---> 7f58449cc6fc
Step 2/6 : WORKDIR /app
---> Using cache
---> 24b4ab64ae6b
Step 3/6 : COPY . .
---> 089d6d837f38
Step 4/6 : RUN yarn install --production
---> Running in c80e446a2ed5
yarn install v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 121.91s.
Removing intermediate container c80e446a2ed5
---> c9b792128cc9
Step 5/6 : CMD ["node", "src/index.js"]
---> Running in a8a7d82b4869
Removing intermediate container a8a7d82b4869
---> cf7f15ee6c79
Step 6/6 : EXPOSE 3000
---> Running in dae6273f632f
Removing intermediate container dae6273f632f
---> e712339a5000
Successfully built e712339a5000
Successfully tagged getting-started:latest
3.使用更新的代码启动新容器。
docker run -dp 127.0.0.1:3000:3000 getting-started
遇到报错信息
root@ub1804:/home/xiaoyue/workdir/dockerdir/getting-started-app# docker run -dp 127.0.0.1:3000:3000 getting-started
4db815634e08b33295e1ada1d0875e4eafc42792c7c091310b0e44cfd6b81abb
docker: Error response from daemon: driver failed programming external connectivity on endpoint gallant_almeida (f6a8c03b30fe1808339816316dee7fd7d6fcf454bceed3c4e816ab70ac643ae5): Bind for 127.0.0.1:3000 failed: port is already allocated.
发生此错误的原因是,在旧容器仍在运行时,无法启动新容器。原因是旧容器已经在使用主机的端口 3000,并且机器上只有一个进程(包括容器)可以侦听特定端口。若要解决此问题,需要删除旧容器。
移除旧容器
1.使用 docker ps 命令获取容器的 ID
2.使用命令 docker stop 停止容器。替换 为 中的 docker ps ID。
3.容器停止后,可以使用命令 docker rm 将其删除。
Note注意:
您可以通过向 docker rm 命令添加 force 标志来停止和删除单个命令中的容器。例如: docker rm -f
启动更新的应用容器
现在,使用命令 docker run 启动更新的应用程序
在 http://localhost:3000 上刷新浏览器,您应该会看到更新的帮助文本【在56行修改的文本信息在图片中最后一行】
总结:
在本部分中,你学习了如何更新和重新生成容器,以及如何停止和删除容器
step 4 共享应用程序 pass
pass
可以推送到阿里云的docker容器仓库;
总结;
在本节中,您学习了如何通过将镜像推送到仓库来共享映像。然后,您转到一个全新的实例,并能够运行新推送的映像。这在 CI 管道中很常见,管道将创建映像并将其推送到仓库,然后生产环境可以使用最新版本的映像。
step 5 持久化数据
如果你没有注意到,每次启动容器时,你的待办事项列表都是空的。为什么会这样?在这一部分中,您将深入了解容器的工作原理。
容器的文件系统
当容器运行时,它会使用映像中的各个层作为其文件系统。每个容器也有自己的“暂存空间”来创建/更新/删除文件。任何更改都不会在另一个容器中看到,即使它们使用相同的映像也是如此。
容器卷的介绍
在前面的实验中,你看到每个容器每次启动时都从映像定义开始。虽然容器可以创建、更新和删除文件,但在删除容器并且 Docker 将所有更改隔离到该容器时,这些更改将丢失。使用卷,您可以更改所有这些内容。
卷提供了将容器的特定文件系统路径连接回主机的功能。如果在容器中装载目录,则在主机上也会看到该目录中的更改。如果在容器重启时装载同一目录,则会看到相同的文件。
卷主要有两种类型。您最终将同时使用这两种方法,但您将从卷装载开始。
保留代办事项数据
默认情况下,待办事项应用将其数据存储在容器文件系统中的 SQLite 数据库 /etc/todos/todo.db 中。如果您不熟悉SQLite,请不要担心!它只是一个关系数据库,将所有数据存储在一个文件中。虽然这对于大型应用程序来说不是最好的,但它适用于小型演示。稍后,您将学习如何将其切换到其他数据库引擎。
由于数据库是单个文件,如果可以将该文件保留在主机上并使其可供下一个容器使用,则它应该能够从上一个容器中断的地方继续。通过创建卷并将其附加(通常称为“挂载”)到存储数据的目录,可以保留数据。当容器写入 todo.db 文件时,它会将数据保留到卷中的主机。
如前所述,您将使用卷装载。将卷装载视为一个不透明的数据桶。Docker 完全管理卷,包括磁盘上的存储位置。您只需要记住卷的名称。
创建卷并启动容器
您可以使用 CLI 或 Docker Desktop 的图形界面创建卷并启动容器。
1使用命令 docker volume create 创建卷。
docker volume create todo-db
- 再次停止并删除 docker rm -f todo 应用容器,因为它仍在运行而不使用持久卷。
- 启动待办事项应用容器,但添加用于指定卷装载 --mount 的选项。为卷命名,并将其装载到 /etc/todos 容器中,该容器将捕获在路径上创建的所有文件。
docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
root@ub1804:/home/xiaoyue# docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
17b58082e48ac86cc473850308decae2b513b3c4b86f70b74830f3682f425261
验证数据是否持久
1.容器启动后,打开应用程序并将一些项目添加到待办事项列表中。(完成作业,做给力的事情,帅)
2.停止并删除待办事项应用的容器。 使用 Docker Desktop 或 docker ps 获取 ID,然后 docker rm -f 将其删除。
- 使用前面的步骤启动新容器。
root@ub1804:/home/xiaoyue# docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
ca6867132e56bab0daa3f9f2ef26342bd80cbd4e537c7407e53b2014f85eb3fa
4 打开应用程序。您应该看到您的项目仍在列表中
5 确认之后,请继续删除容器
深入了解卷
很多人经常问:“当我使用卷时,Docker 将我的数据存储在哪里?如果您想知道,可以使用该 docker volume inspect 命令
root@ub1804:/home/xiaoyue# docker volume inspect todo-db
[
{
"CreatedAt": "2024-06-02T00:40:20+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
是 Mountpoint 数据在磁盘上的实际位置。请注意,在大多数计算机上,您需要具有 root 访问权限才能从主机访问此目录。
增加内容,通过sqlite3工具访问对应数据库位置,查看表中数据内容
root@ub1804:/var/lib/docker/volumes/todo-db/_data# ls
todo.db
root@ub1804:/var/lib/docker/volumes/todo-db/_data# pwd
/var/lib/docker/volumes/todo-db/_data
root@ub1804:/var/lib/docker/volumes/todo-db/_data# sqlite3 todo.db
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .tables
todo_items
sqlite> SELECT * FROM todo_items ;
081888eb-efa6-4477-b6c2-87face70ae8b|drink|0
835307a4-4dcd-4a88-a503-0ee4eecf42a6|eat|0
ea581033-9483-4905-a9f7-676fd28de649|touch|0
sqlite> .quit
总结:
本部分介绍了如何保留容器数据。