更好的阅览体验请移步至:zhengxiaoping.xyz/fullstack/D…
本文适用于第一次入门Docker的新手,假如你开端注意到Docker,恭喜你!你将成为一个美好的人。因为在学完Docker后,相信你会跟我一样,感叹与Docker的相识简直是 相见恨晚!
假如告诉你,能够用 一行指令将nginx运转起来,你会不会感到惊奇?
假如告诉你,还是 一行指令,不仅将nginx运转起来,而且将你的网站运转在其间 ,你是否会感到惊奇?
先不要惊奇。让咱们现在就开端动手,将上面不可思议的工作变成现实!
装置Docker
在开端学习Docker常识前,先花几分钟的时刻装置Docker。引荐以Windows作为入门Docker的渠道,因为Windows版的Docker Desktop有很良好的界面,对于新手而言十分友好。
下载链接:www.docker.com/
其他系统的装置也是十分简略、快速的,参考官网的装置文档即可。
开胃菜:在Docker上跑一个服务器
首要,咱们在本地D盘的hello-docker目录,新建一个index.html文件,内容如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
Hello, Docker!
</body>
</html>
然后,翻开控制台,运转一行指令:
docker run -d -p 80:80 -v d:/hello-docker:/usr/share/nginx/html nginx:latest
紧接着,咱们翻开 http://localhost/
,奇妙的工作产生了:
整个进程不到1分钟,咱们现已将开发的内容布置到nginx服务器上了!!
是的,这便是Docker。事实上,运用Docker,你只需求输入一行指令,就能够将一个整合了多个服务器及各种中间件的庞大系统运转起来。更为美妙的是,当你为你的服务替换主机时,依然只需求一行指令,就搞定一切工作。
了解Docker
前面咱们经过一行指令成功把一个静态web网页布置到了nginx上,对于运用者而言会十分猎奇,Docker到底是怎么做到这一切的呢?
事实上, 你的软件怎么合作运转是确认的 ,例如一个简略的博客系统,至少由以下三个部分构成:
- 数据库(存储数据)
- 运用服务器(供给运用接口)
- web静态服务器(前端运用布置)
为了让你的博客运用跑起来,你或许需求这些进程:
- 装置mysql,设置用户名与密码,并运转
- 运转一个node服务器(如express或koa),衔接mysql,这个进程需求指定主机名、端口、用户名、密码等信息
- 运转一个nginx服务器,将开发的代码布置在其上,此进程根据需求或许需求修正nginx的装备文件
你会发现,不论你换多少台主机进行布置,你总是要重复上面的进程,而这些进程只是在第一次考虑它时具有价值,后续的一切劳作都是冗余的、无意义的。
Docker便是来 办理这些进程 的,正因为系统需求哪些配件以及各部分怎么合作运转是确认的,因而,能够将这些制造为一个标准的流程,由Docker去办理。
正如它的姓名(Dock:船坞),Docker是一个码头工人,担任搬运你的货品(运用),将你的工作中最为枯燥、无意义的一部分完全接收。
长话短说,你能够认为:
有了Docker,你再也不需求亲力亲为去装置和装备那些复杂的软件,软件供应商会将自己的软件以及它的运转环境打包好,你只要叮咛Docker将它们搬过来,然后按一下开机键,就能够运转了。
了解镜像与容器的联系
前面的叙说涉及到Docker最中心的两个概念:软件供应商打包好的可运转的货品,称为 镜像 ,而你运转的,称为 容器 。(注意,镜像与容器并不是一对一的联系,这里的叙说并不准确,详情请继续阅览)
假如你是一个有面向目标开发经验的开发者,了解镜像与容器的联系十分简略,镜像便是类,容器便是目标(或实例)。
假如你不是,那么你能够简略了解这些联系:
- 镜像 = 菜谱。 例如nginx镜像就如鱼香茄子的菜谱,具体说明了鱼香茄子的制造进程(调料、原料、锅、火候等);
- Docker = 厨师。 Docker从码头工人摇身一变成为米其林大厨,它担任依照菜谱的要求准备资料并烹饪你的美食;
- 容器 = 菜。 当Docker这个“大厨”完成烹饪后,你就取得了一份鱼香茄子。
因而,你能够让Docker炒5份鱼香茄子(一个镜像运转多个容器,结构集群环境),同一份菜,或许有多个菜谱,或许有的菜谱做出的鱼香茄子会有一些地方特色,例如广东的鱼香茄子会加入沙茶酱(同一类镜像或许有多个版别,有一些会供给一些已有装备或高档特性,例如nginx的官方镜像和其他厂商实现的镜像)。
同时,不同的菜,菜谱的厚度是不同的,西红柿炒蛋或许1页就够,可是满汉全席或许需求一本书(不同镜像的大小是纷歧的,能够简略认为镜像要做的工作越多越杂,镜像就越大)。
怎么将一个容器跑起来?
还是以菜谱、厨师与菜的联系来了解,首要:
第一步:你得有个厨师(装置Docker)
第二步:要根据你的需求,获取你的菜谱,这个进程被称为拉取镜像。
例如你想取得一个nginx镜像,只需求运用这个指令即可:
docker pull nginx:latest
# 或:
# docker image pull nginx:latest
你能够运用 docker image ls
或直接在Docker Desktop中查看刚刚拉取的镜像:
第三步:叮咛厨师,做菜!(运转镜像,容器化/实例化)
docker run -d -p 80:80 nginx:latest
最终,翻开 http://localhost
,就能够食用你的美食了!
制造自己的“菜谱”
前面咱们说过,镜像是菜谱,Docker是厨师,容器是菜,那咱们能不能让Docker在做菜的时候放点其他调料呢?不能。厨师会忠实地依照菜谱做菜,并不会改造菜谱。那怎么做一份定制的鱼香茄子呢?你需求履行以下进程:
- 依照鱼香茄子的菜谱,制造一份自己的菜谱(例如在出锅前放一勺糖);
- 叮咛厨师,依照自己的菜谱做菜,做出契合自己口味的鱼香茄子。
这个制造定制菜谱的进程便是 镜像制造 。
镜像制造需求的中心元素便是 Dockerfile
,相信你曾经不止一次看到过它,它便是“菜谱”,用来描绘你定制的这道菜的制造进程。让咱们来看一个简略的比如:
FROM nginx:latest
COPY . /usr/share/nginx/html
-
FROM nginx:latest
根据nginx镜像制造新的镜像,比如根据鱼香茄子的菜谱制造自己的鱼香茄子菜谱 -
COPY . /usr/share/nginx/html
将目录内容拷贝到nginx的入口目录,这样未来运转nginx时,就能跑起自己的项目了
接下来,你需求开端制造镜像:
docker build -t mynginx:latest .
不如?现在就来运转一个博客?
首要,咱们需求运转一个数据库来存储咱们博客的数据,不如就mysql吧。翻开指令行运转指令:
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=blog mysql:latest
指令详解:
-
-d
后台运转 -
-p 3306:3306
露出端口,将内部3306端口映射到本机3306端口(假如本机存在mysql并已运转,则会产生端口占用报错) -
-e MYSQL_ROOT_PASSWORD=root
设置mysql的root用户密码为root
-
-e MYSQL_DATABASE=blog
设置mysql默认数据库,这里设置为blog,会主动创立 -
mysql:latest
运用mysql的latest版别作为镜像
mysql容器运转后,你能够经过例如Navicat等数据库客户端衔接,因为它的端口现已露出到了本机。
接下来,咱们来运转一个node服务器并衔接mysql。
咱们选择koa作为结构,首要,装置依靠:
pnpm i koa mysql2
# yarn add koa mysql2
# npm i koa mysql2
db.js
const mysql = require('mysql2')
const { MYSQL_HOST } = require('./config')
let pool
exports.createPool = function() {
pool = mysql.createPool({
host: MYSQL_HOST,
port: '3306',
user: 'root',
password: 'xpzheng',
database: 'hello',
charset: 'utf8mb4',
})
return pool
}
exports.init = function() {
return new Promise((resolve, reject) => {
pool.getConnection((err, conn) => {
if (err) return console.error(err)
conn.execute('drop table if exists t_blog;', (err) => {
if (err) return reject(err)
conn.execute(`create table t_blog (
title varchar(255),
text text
);`, (err2) => {
if (err2) return reject(err2)
resolve()
})
})
})
})
}
index.js
const Koa = require('koa')
const cors = require('@koa/cors')
const Router = require('@koa/router')
const { createPool, init } = require('./db')
const app = new Koa()
const router = new Router()
let db
function query(sql) {
return new Promise((resolve, reject) => {
db.query(sql, (err, results) => {
if (err) return reject(err)
resolve(results)
})
})
}
function execute(sql) {
return new Promise((resolve, reject) => {
db.getConnection((err, conn) => {
if (err) return reject(err)
conn.execute(sql, err2 => {
if (err2) return reject(err2)
resolve()
})
})
})
}
router.get('/', ctx => {
ctx.redirect('hello')
})
router.get('/hello', ctx => {
ctx.body = 'Hello, Koa!'
})
router.get('/blog/add', async(ctx) => {
if (!ctx.query.title || !ctx.query.text) {
ctx.body = '请传入标题与内容'
return
}
await execute(`
insert into t_blog (title, text) values ('${ctx.query.title}', '${ctx.query.text}')
`)
ctx.body = true
})
router.get('/blog/list', async(ctx) => {
const result = await query(`select * from t_blog`)
ctx.body = result
})
app
.use(cors())
.use(router.routes())
.use(router.allowedMethods())
.use(async(ctx, next) => {
next()
})
;(async function() {
try {
db = createPool()
await init();
} catch (err) {
console.error(err)
}
app.listen(3000)
})()
在 db.js
中,咱们衔接了msyql并创立了 t_blog
表。index.js
文件中,咱们供给了一个增加文章与查询文章列表的接口。
接下来,咱们再创立一个vite项目,访问这个node服务,增加或获取文章数据。
最终,将该项目布置在nginx中,访问作用如下:
至此,咱们将整个博客运用搭建并布置成功了!
具体代码请参考:github.com/shoppingzh/…
Docker学习道路
以下引荐了一个较为合理的Docker学习道路,不论你选择的道路是什么,还是引荐从官方文档下手。
- 装置Docker
- 了解镜像与容器的联系
- 运用官方镜像,在Docker上跑一个服务器
- 自己制造一个镜像
- 常用Docker指令
- 制造自己的镜像,跑一个简略的运用
- 进一步学习:知道网络与卷
- 多容器布置面临的窘境
- 知道Docker Compose
- Docker常识系统
- 分布式布置
- 未完待续…
常用指令
镜像
列出一切镜像
docker image ls
删去镜像
docker image rm nginx:latest
制造镜像
docker build -t myimage:1.0 . -f /xxx/yyy/Dockerfile
容器
运转容器
docker run -d -p 80:80 --mount source=nginx,target=/usr/share/nginx/html nginx:latest
-
-d
后台运转 -
-p
露出端口 -
--mount
挂载卷
中止运转容器
docker stop 5f79d10d97
5f79d10d97
表明容器运转的仅有标识。
列出正在运转的镜像
docker container ls
删去容器
docker container rm 5f79d10d97
卷
创立卷
docker volume create nginx
列出一切卷
docker volume ls
运转时绑定卷
办法1:指定卷名(需求先创立卷,假如没创立,docker会主动创立)
docker run -d -p 80:80 --mount source=my-volume,target=/usr/share/nginx/html nginx:latest
办法2:自行指定目录(更灵活)
docker run -d -p 80:80 --mount type=bind,src=d:/nginx,target=/usr/share/nginx/html nginx:latest
删去指定卷
docker volumn rm nginx
网络
列出一切网络
docker network ls