Docker 快速上手学习入门教程 1
目录
1、docker 的基础概念
2、怎样打包和运行一个应用程序?
3、如何对 docker 中的应用程序进行修改?
4、如何对创建的镜像进行共享?
5、如何使用 volumes 名称对容器中的数据进行存储?// 数据挂载
6、另一种挂载方式:目录挂载
7、实现容器之间的相互通信
8、使用 Docker Compose 简化多个容器之间的共享操作
1、docker 的基础概念
什么是容器?
官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。
什么是容器镜像?
容器运行的依赖文件就是镜像,通过镜像可以创建多个容器。
2、怎样打包和运行一个应用程序?
(1)获取程序源文件
准备:需要安装 git,使用 git 拉取远程代码到本地。 下边程序是一个 docker 官方的示例:
git clone https://github.com/docker/getting-started.git
(2)创建容器镜像
创建容器镜像,需要用到 Dockerfile 文件。Dockerfile 只是一个基于文本的文件,没有文件扩展名。Dockerfile 中包含 Docker 用来创建容器映像的指令脚本。
创建 Dockerfile 文件:在下载的 getting-started 项目中创建空的 Dockerfile 文件(注意该文件没有任何文件格式)
填充 Dockerfile 文件内容如下(关于 Dockerfile 文件的编写后续会有专门的介绍,这里只需要知道创建容器镜像需要使用到 Dockerfile 文件即可):
# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000
在 Dockerfile 文件的当前目录下(app 目录下),通过 docker build 命令创建容器镜像:
docker build -t getting-started .
- -t 表示镜像的 tags,这里的标签名称为 getting-started
- . 表示 docker build 命令从当前文件夹下寻找 Dockerfile 文件
(3)启动运行容器
创建镜像成功后,使用 docker images 命令就可以在系统中查看到创建的镜像了。查看镜像后使用 docker run 命令运行创建的镜像文件:
docker run -dp 3000:3000 getting-started
-d 表示在后台运行容器,-p 表示创建容器和本机的端口映射,端口映射是必须的,不然无法对容器中的程序进行访问。// 有人也说容器是一个虚拟机,这样想似乎能更好的解释端口映射
访问 http://localhost:3000/ 出现以下界面,说明容器启动成功:
3、如何对 docker 中的应用程序进行修改?
如果我们修改了应用程序,要使修改生效,就需要重新创建镜像文件(重复文章第二节中的过程)。需要注意的是,为避免端口冲突,应该先停止正在运行的容器。以下是操作容器的一些命令:
docker ps 可以获取到容器的id
docker stop <the-container-id> 通过id停止一个容器
docker rm <the-container-id> 容器停止后,删除一个容器
docker rm -f <the-container-id> -f 即force,表示强制删除
4、如何对创建的镜像进行共享?
(1)创建一个远程仓库
如果没有 Docker ID,可以在 Docker Hub 上注册用户,然后使用 Docker Hub 创建远程仓库。创建远程仓库的步骤在官方文档中有详细介绍(文档链接地址在文章最后),大致与 git 创建远程仓库,然后推送代码的过程相似。
(2)把镜像推送到远程仓库
把镜像推送到远程仓库后,其他人就可以下载到你的镜像了,常用的命令如下:
docker push YOUR-USER-NAME/getting-started:tagname // 推送镜像
docker tag getting-started YOUR-USER-NAME/getting-started //给镜像打标签
docker push YOUR-USER-NAME/getting-started // 拉取镜像
5、如何使用 volumes 名称对容器中的数据进行存储?// 数据挂载
每次启动容器时,之前容器更新的数据都会被清除。这是因为每个容器都有自己“独立的空间”来创建/更新/删除文件。这些更改都不会在另一个容器中看到,即使它们使用的是相同的镜像。// 容器是相互隔离的
解决上述问题的思路:使用 volumes 对数据进行存储。
通过 volumes 可以将容器中的具体文件系统路径挂载到主机。如果容器中的一个目录被挂载,那么在主机上也会看到该目录中的更改。如果我们在容器重新启动时挂载同一个目录,我们将看到相同的文件。// docker 提供了两种挂载方式:数据挂载和目录挂载
(1)使用 docker volume create 命令创建 volume,todo-db 为 volume 的名称
docker volume create todo-db
(2)使用 volume 名称进行挂载,/etc/todos 路径下的所有更改都会同步到 volume 中,使用同一个 volume 的其他容器也能够看到相同的信息
// 默认情况下,todo 应用程序将其数据存储在 SQLite 数据库中的 /etc/todos/todo.db 文件中,
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
那么,当我们创建容器卷(volume)后,容器中的文件具体保存在物理机的哪个地方呢?使用 docker volume inspect 命令,查看容器卷的详细信息:
$ docker volume inspect todo-db
[{"CreatedAt": "2023-02-07T01:34:40Z","Driver": "local","Labels": {},"Mountpoint": "/var/lib/docker/volumes/todo-db/_data","Name": "todo-db","Options": {},"Scope": "local"}
]
Mountpoint 就是文件在磁盘上的具体存储路径(自动生成的),但是,在大多数计算机上,这个路径需要具有根访问权限才能从主机访问此目录。// windows 系统也是这个路径,这个路径在 win 系统上不能直接访问,因此会比较麻烦
6、另一种挂载方式:目录挂载
目录挂载:允许将主机文件系统中的一个目录共享到容器中。以下是目录挂载和容器卷挂载的区别:
命名卷(volume) | 绑定挂载(目录挂载) | |
主机存储位置 | Docker 选择 | 自定义 |
绑定示例 |
type=volume, src=my-volume,target=/usr/local/data |
type=bind, src=/path/to/data,target=/usr/local/data |
用容器内容填充新卷 | 是 | 否 |
支持volume驱动程序 | 是 | 否 |
示例:在目录 getting-started/app 输入如下命令(win),注意,使用的是 PowerShell 而不是 cmd 命令启用的黑窗口,如果仍然报错可以使用编辑工具把以下命令编辑成一行
docker run -dp 3000:3000 `-w /app --mount type=bind,src="$(pwd)",target=/app `node:18-alpine `sh -c "yarn install && yarn run dev"
- -dp 3000:3000 端口映射
- -w /app 设置工作目录或命令运行的当前目录
- --mount type=bind,src="$(pwd)",target=/app 把主机的当前目录绑定到容器中的 /app 目录
- node:18-alpine 程序运行需要依赖的基础镜像(在上文 DockerFile 中也有写)
- sh -c "yarn install && yarn run dev" 使用 sh 运行 shell,使用 yarn install 安装依赖包,使用 yarn run dev 启动一个服务(dev 脚本定义在 getting-started\app\package.json 文件中,它会启动 nodemon)
nodemon 是一个工具,当程序有改动时,nodemon 程序用来自动重启容器。当然,我们也可以用第二节提到的步骤对程序进行打包然后重新启动。
容器启动后,使用如下命令查看 docker 的运行日志:
docker logs -f <container-id>
7、实现容器之间的相互通信
默认情况下,docker 之间是相互独立的,彼此之间相互隔离,那么怎么样让相互隔离的两个容器进行通信呢?// 比如部署应用程序的 docker 和部署数据库的 docker 之间进行通信
答案是:在 docker 之间建立通信网络,在同一个通信网络的不同容器之间可以进行相互通信。一般将容器放到一个网络中有两种方法:1、在启动容器时进行分配,2、连接到已有的容器的网络。下边将分别使用到这两种方式。// 每一节的案例都需要关闭之前启动的容器,避免端口冲突
(1)创建一个通信网络
docker network create todo-app
(2)启动一个 mysql 容器,并连接到 todo-app 网络(win PowerShell 版)
docker run -d `--network todo-app --network-alias mysql `-v todo-mysql-data:/var/lib/mysql `-e MYSQL_ROOT_PASSWORD=secret `-e MYSQL_DATABASE=todos `mysql:8.0
- --network-alias 指定运行容器的别名,使用别名替换掉具体的 ip,更方便在网络中查找容器
- -v todo-mysql-data:/var/lib/mysql 该命令会自动创建容器卷 todo-mysql-data,然后存储mysql中的数据库数据(/var/lib/mysql 为数据库存储数据的路径)
为了查看数据库容器是否已经启动,可以尝试进入容器进行查看:// 密码是 secret,脚本中有指定
docker ps // 查看正在运行中的容器
docker exec -it <mysql-container-id> mysql -u root -p
如果输入密码可进行登录,说明数据库已经启动了,尝试以下命令,验证 mysql 正常
mysql> SHOW DATABASES;
mysql> exit;
那么当 mysql 启动后,怎样找到这个容器呢?答案是,使用一个 nicolaka/netshoot 的网络工具。首先我们通过 docker 来安装这个工具
docker run -it --network todo-app nicolaka/netshoot
安装完后,就可以使用这个 DNS 工具了。//下边的 mysql 就是启动容器时指定的别名
dig mysql/容器id
然后就能看到 mysql 容器的相关网络信息 :
我们看到 mysql 容器的 ip 为 172.19.0.2(todo-app 网络中的地址),一般来说,我们仅仅通过 mysql 别名就可以定位到这个地址了,而不需要显示去指定它。
(3)启动应用程序容器,并连接到 mysql 容器
todo 应用程序支持设置一些环境变量来指定 MySQL 连接设置
- MYSQL_HOST - MySQL server 主机名称
- MYSQL_USER - 数据库连接用户
- MYSQL_PASSWORD - 数据库连接密码
- MYSQL_DB - 连接的 mysql 的具体数据库
在 getting-started\app 目录下运行以下命令(win PowerShell 版)
docker run -dp 3000:3000 `-w /app -v "$(pwd):/app" `--network todo-app `-e MYSQL_HOST=mysql `-e MYSQL_USER=root `-e MYSQL_PASSWORD=secret `-e MYSQL_DB=todos `node:18-alpine `sh -c "yarn install && yarn run dev"
运行成功后,就可以查看到 docker 的启动日志了
此时,我们再打开程序http://localhost:3000/往项目中添加 items,然后进入到数据库容器就可以查看到刚才添加的数据了
docker exec -it <mysql-container-id> mysql -p todos //进入数据库容器
select * from todo_items; // 查看表中数据
至此,我们就实现了两个容器之间的相互通信。
8、使用 Docker Compose 简化多个容器之间的共享操作
Docker Compose 用于帮助定义和共享多容器中的应用程序。通过 Compose,我们可以创建一个 YAML 文件来定义服务,并通过一个命令,就可以启动或停止所有服务。
(1)安装 Docker Compose
如果在 win 环境安装了 Docker Desktop,那么默认情况下就已经安装了 Docker Compose,如果是 linux 环境那么需要单独进行安装,安装教程点击这里。安装完后可以查看该工具的版本:
docker compose version
(2)编写 Compose file 文件
在 getting-started\app 目录下创建一个 docker-compose.yml 文件
然后在 docker-compose.yml 文件中填充以下内容:// 文档的具体编写参照文末的文档,这里只介绍大致步骤
services:app:image: node:18-alpinecommand: sh -c "yarn install && yarn run dev"ports:- 3000:3000working_dir: /appvolumes:- ./:/appenvironment:MYSQL_HOST: mysqlMYSQL_USER: rootMYSQL_PASSWORD: secretMYSQL_DB: todosmysql:image: mysql:8.0volumes:- todo-mysql-data:/var/lib/mysqlenvironment:MYSQL_ROOT_PASSWORD: secretMYSQL_DATABASE: todosvolumes:todo-mysql-data:
(3)批量启动容器
在 getting-started\app 目录下执行以下命令,-d 表示后台启动
docker compose up -d
然后你会看到如下输出信息:
信息中显示容器卷和通信网络都被创建了,默认情况下,Docker Compose 会自动为应用程序堆栈创建一个网络(这就是为什么我们不需要在 Compose 文件中定义一个网络的原因)。
至此,所有的容器就都成功启动了,如果你安装了 Docker Desktop,你将看到以下界面:
(4)批量关闭和移除容器
使用以下命令可以批量关闭和移除容器
docker compose down
需要注意的是,以上命令并不会删除创建的容器卷,删除容器卷需要使用单独的命令来操作。
参考文档:Overview | Docker Documentation
Docker 快速上手学习入门教程 1相关推荐
- Docker 快速上手学习入门教程
原文链接:http://tabalt.net/blog/docker... Docker是一个使用Golang开发的开源应用容器引擎,让开发者可以打包应用和依赖到一个轻量级.可移植的镜像中,然后分发到 ...
- [Docker]Docker快速上手学习笔记
0. 学习的一些疑问 如何热更新镜像(images)?(你可以快速启动或者销毁容器.这种时间几乎是实时的) 如何热更新游戏服? 好处在于各个应用之间环境相互独立,即使某一个容器崩溃也不会影响到其它容器 ...
- 深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器
深度学习入门教程UFLDL学习实验笔记一:稀疏自编码器 UFLDL即(unsupervised feature learning & deep learning).这是斯坦福网站上的一篇 ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-代码生成器的使用
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-基于Osharp实现自己的业务功能...
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- Cloud Computing:基于无影云电脑利用Python语言实现绘制“可爱小老虎”虎年快乐及无影云电脑简介、应用场景、使用体验(五步快速上手)分享图文教程之详细攻略
Cloud Computing:基于无影云电脑利用Python语言实现绘制"可爱小老虎"虎年快乐及无影云电脑简介.应用场景.使用体验(五步快速上手)分享图文教程之详细攻略 目录 无 ...
- 深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening
深度学习入门教程UFLDL学习实验笔记三:主成分分析PCA与白化whitening 主成分分析与白化是在做深度学习训练时最常见的两种预处理的方法,主成分分析是一种我们用的很多的降维的一种手段,通 ...
- caffe linux 教程,Caffe 深度学习入门教程 - 安装配置Ubuntu14.04+CUDA7.5+Caffe+cuDNN_Linux教程_Linux公社-Linux系统门户网站...
安装配置Ubuntu14.04+CUDA7.5+Caffe+cuDNN 一.版本 Linux系统:Ubuntu 14.04 (64位) 显卡:Nvidia K20c cuda: cuda_7.5.18 ...
- jsx 调用php,JavaScript_JavaScript的React框架中的JSX语法学习入门教程,什么是JSX?
在用React写组件的 - phpStudy...
JavaScript的React框架中的JSX语法学习入门教程 什么是JSX? 在用React写组件的时候,通常会用到JSX语法,粗看上去,像是在Javascript代码里直接写起了XML标签,实质上 ...
最新文章
- ASP.net实现无扩展名的URL重写。简单、方便、无需ISAPI
- FFmpeg4.1 视频解码,保存原始YUV数据
- Asp.net面试题之一
- 杭电1010java实现dfs
- 【温故知新】HTML学习笔记(下)
- Python抓取网页数据的终极办法
- 《汇编语言》-王爽-实验7
- spring-boot 速成(8) 集成druid+mybatis
- 编译出现ARM与THUMB冲突
- ~~单调队列(数据结构)(附题目)
- linux shell locate,shell学习之locate和find命令
- 中国最惨创业者的惨痛教训!
- 【linux】如何查看和解压缩rpm文件内容
- 华为招聘状态码RSA解密方法
- 数据价值应用—数据可视化
- 谈《西游记》和泛项目
- 真无线蓝牙耳机哪个好用?学生党蓝牙耳机性价比排行榜
- 两个div右侧固定,左侧自适应屏幕
- shp导入Oracle
- Android 一体机研发之修改系统设置————声音
热门文章
- 基于android的记账本国内外研究现状,基于android系统的记账本的设计与实现.doc
- 魔力宝贝手游版 服务器维护,魔力宝贝手游10月24日更新维护公告 各大更新内容...
- html 纵向滚动条,css设置纵向滚动条
- 检测椭圆的长短轴参数
- TSC Deluxe 300 pro 打印机驱动
- 三维地图打造数、实融合底座
- 没有大数据就没有智慧城市
- 冰羚Planned features.md翻译
- 「CF1463A」暗黑地牢
- JAVA计算:用 100 元钱买 100 支笔,其中钢笔 3 元 / 支,圆珠笔 2 元 / 支,铅笔 0.5 元 / 支,问钢笔、圆珠笔和铅笔可以各买多少支 ?