文章目录
- 一、简介和安装
- 1)什么是docker
- 2)跟虚拟机的对比
- 3)打包、分发、部署介绍
- 4)Docker 部署的优势
- 5)Docker 通常用来做什么
- 6)重要概念:镜像、容器
- 7)安装链接
- 8)docker启动报错解决方法
- 9)子系统安装步骤
- 10)设置镜像加速源(docker服务器在国外)
- 二、docker快速安装软件
- 1)直接安装的缺点
- 2)docker安装优点
- 3)演示Docker安装Redis
- 4)安装wordpress举例:
- 5)ELK安装步骤说明
- 6)更多相关命令
- 三、制作自己的镜像
- 1)举例制作项目说明
- 2)编写 Dockerfile并运行项目(描述依赖哪些库,为安装做准备)
- 3)Build 为镜像(安装包)和运行
- 4)docker编译指令说明
- 四、目录挂载
- 1)之前制作镜像之后存在的问题
- 2)几种挂载方式
- 3)挂载演示
- 五、多容器通信
- 1)学习目标
- 2)创建虚拟网络
- 3)演示
- 六、Docker-Compose
- 1)现存问题
- 2)安装docker compose
- 3)编写docker-compose.yml文件,描述依赖哪些服务(默认使用同一个网络)
- 4)跑起来
- 七、发布和部署
- 1)镜像仓库(存储build出来的安装包)
- 2)上传镜像
- 3)阿里云容器托管
- 八、备份和迁移数据
- 1)迁移方式介绍
- 2)备份和导入Volume的流程
- 3)备份MongoDB的数据演示
- 4)恢复 Volume 数据演示
一、简介和安装
1)什么是docker
Docker 是一个应用打包、分发、部署的工具
你也可以把它理解为一个轻量的虚拟机,它只虚拟你软件需要的运行环境,多余的一点都不要,
而普通虚拟机则是一个完整而庞大的系统,包含各种不管你要不要的软件。
2)跟虚拟机的对比
3)打包、分发、部署介绍
- 打包:
就是把你软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包 - 分发:
你可以把你打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装 - 部署:
拿着“安装包”就可以一个命令运行起来你的应用,自动模拟出一摸一样的运行环境,不管是在 Windows/Mac/Linux。
4)Docker 部署的优势
- 概念
常规应用开发部署方式:自己在 Windows 上开发、测试 --> 到 Linux 服务器配置运行环境部署。
问题:
怎么在我机器上跑都没问题,怎么到服务器就各种问题了?
- 解决方法
用 Docker 开发部署流程:自己在 Windows 上开发、测试 --> 打包为 Docker 镜像(可以理解为软件安装包) --> 各种服务器上只需要一个命令部署好 - 优点
确保了不同机器上跑都是一致的运行环境,不会出现我机器上跑正常,你机器跑就有问题的情况。
5)Docker 通常用来做什么
1)应用分发、部署,方便传播给他人安装。特别是开源软件和提供私有部署的应用
2)快速安装测试/学习软件,用完就丢(类似小程序),不把时间浪费在安装软件上。例如 Redis / MongoDB / ElasticSearch / ELK
3)多个版本软件共存,不污染系统
,例如 Python2、Python3,Redis4.0,Redis5.0
Windows 上体验/学习各种 Linux 系统
6)重要概念:镜像、容器
- 镜像:
可以理解为软件安装包,可以方便的进行传播和安装。 - 容器:
软件安装后的状态,每个软件运行环境都是独立的、隔离的,称之为容器。
7)安装链接
- win桌面版:
https://www.docker.com/products/docker-desktop - linux服务器版:
https://docs.docker.com/engine/install/#server
8)docker启动报错解决方法
- 解决方法:
控制面板->程序->启用或关闭 windows 功能,开启 Windows 虚拟化和 Linux 子系统(WSL2)
9)子系统安装步骤
1)wsl --install -d Ubuntu
命令行安装可能太慢,你也可以打开微软商店 Microsoft Store 搜索 Linux 进行安装
2)设置开机启动 Hypervisor
bcdedit /set hypervisorlaunchtype auto
注意要用管理员权限打开 PowerShell
3)win的注意确保 BIOS 已开启虚拟化,下图检查是否已开启好
如果是已禁用,请在开机时按 F2 进入 BIOS 开启一下,不会设置的可以网上搜索下自己主板的设置方法,Intel 和 AMD 的设置可能稍有不同
4)若出现下图错误,点击链接安装最新版本的 WSL2,安装完后记得点击restart重新启动
10)设置镜像加速源(docker服务器在国外)
阿里云需要去自己注册一个号
二、docker快速安装软件
1)直接安装的缺点
(1)安装麻烦,可能有各种依赖,运行报错。例如:WordPress,ElasticSearch,Redis,ELK
(2)可能对 Windows 并不友好,运行有各种兼容问题,软件只支持 Linux 上跑
(3)不方便安装多版本软件,不能共存。
(4)电脑安装了一堆软件,拖慢电脑速度。
(5)不同系统和硬件,安装方式不一样
2)docker安装优点
(1)一个命令就可以安装好,快速方便
(2)有大量的镜像,可直接使用
(3)没有系统兼容问题,Linux 专享软件也照样跑
(4)支持软件多版本共存
(5)用完就丢,不拖慢电脑速度
(6)不同系统和硬件,只要安装好 Docker 其他都一样了,一个命令搞定所有
3)演示Docker安装Redis
(1)Redis 官网:https://redis.io/
官网下载安装教程只有源码安装方式,没有 Windows 版本。想要自己安装 windows 版本需要去找别人编译好的安装包。
(2)Docker 官方镜像仓库查找 Redis :
(3)一个命令跑起来:
- 命令
docker run -d -p 6379:6379 --name redis redis:latest
docker run 表示docker运行一个软件
-p 暴露端口6379
--name 给这个软件命名
redis:latest 采用redis的最新版本(或是采用固定版本,比如5.0.14)
- 命令效果
- 可以看到镜像已经拉过来了,100MB
- docker文档参考
命令参考:https://docs.docker.com/engine/reference/commandline/run/
- 进入redis终端
4)安装wordpress举例:
- 进入wordpress的docker页签,并复制文档,保存到docker-compose.yml里面
- 在docker-compose文件的目录,右键打开powershell
docker-compose up -d
- 创建实例结束,到docker里面可以看到mysql和wordpress的镜像
- 可以看到容器里面进程已经后台跑起来了
- 本地访问8080访问wordpress
5)ELK安装步骤说明
- 安装指令
安装ELK指令:
docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk sebp/elk
-
内存不够解决办法 转到用户目录 cd ~,路径类似这个:C:\Users<UserName>
创建 .wslconfig 文件填入以下内容
[wsl2]
memory=10GB # Limits VM memory in WSL 2 to 4 GB
processors=2 # Makes the WSL 2 VM use two virtual processors
生效配置,命令行运行
wsl --shutdown
6)更多相关命令
docker ps 查看当前运行中的容器
docker images 查看镜像列表
docker rm container-id 删除指定 id 的容器
docker stop/start container-id 停止/启动指定 id 的容器
docker rmi image-id 删除指定 id 的镜像
docker volume ls 查看 volume 列表
docker network ls 查看网络列表
https://docker.easydoc.net/doc/81170005/cCewZWoN/AWOEX9XM https://www.bilibili.com/video/BV11L411g7U1?p=2&vd_source=27ec8b3b09d2a66ceeb9dbe961a247d3
三、制作自己的镜像
1)举例制作项目说明
- 代码传送门
示例项目代码:https://github.com/gzyunke/test-docker - 项目简介
这是一个 Nodejs + Koa2 写的 Web 项目,提供了简单的两个演示页面 - 项目依赖
软件依赖:nodejs - 项目依赖库
项目依赖库:koa、log4js、koa-router
2)编写 Dockerfile并运行项目(描述依赖哪些库,为安装做准备)
FROM node:11 --表示以这个为底
MAINTAINER easydoc.net --维护者是easydoc.net
# 复制当前目录下的源码到/app目录
ADD . /app
# 设置容器启动后的默认运行目录
WORKDIR /app
# 运行命令,安装依赖库
# RUN 命令可以有多个,但是可以用 && 连接多个命令来减少层级。
# 例如 RUN npm install && cd /app && mkdir logs
RUN npm install --registry=https://registry.npm.taobao.org
--注释
--1)这里的 --registry= 表示指定的加速域
--2)npm install 安装依赖
# CMD 指令只能一个,是容器启动后执行的命令,算是程序的入口。
# 如果还需要运行其他命令可以用 && 连接,也可以写成一个shell脚本去执行。
# 例如 CMD cd /app && ./start.sh
# 运行这个项目
CMD node app.js
- npm install 自动安装的依赖
(package.json)
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "app.js",
"dependencies": {
"koa": "^2.13.1",
"log4js": "^3.0.6",
"redis": "^4.0.0-rc.3",
"mongodb": "^3.6.9",
"koa-websocket": "^6.0.0",
"koa-router": "^7.4.0"
},
"scripts": {
"start": "cross-env PORT=8080 node app"
},
"author": "",
"license": "ISC"
}
- app.js(http输入回馈效果)
let Koa = require('koa');
let app = new Koa();
// const redis = require('redis');
// let rds = redis.createClient({url: "redis://redis:6379"});
// rds.on('connect', ()=> console.log('redis connect ok'))
// rds.connect();
let log4js = require('log4js');
log4js.configure('./log4js.json');
log4js.level = 'DEBUG';
let logger = log4js.getLogger('app');
let Router = require('koa-router');
let router = new Router;
router.all('/', async ctx =>{
logger.info('on index page')
ctx.body = `index page`
});
router.all('/hello/:name', async ctx =>{
let name = ctx.params.name
logger.info('on hello page')
ctx.body = `hello ${name ? name : 'world'}`
});
// router.all('/redis', async ctx =>{
// let count = await rds.incr("count")
// logger.info(`on test redis page, count ${count}`)
// ctx.body = `on test redis page, 44 count ${count} `
// });
app.use(router.routes());
let port = process.env.PORT || 8080;
try{
app.listen(8080);
logger.info('Server started successfully and listened on '+ port +'\n'+'http://localhost:'+port);
}catch(err){
console.error(err);
}
3)Build 为镜像(安装包)和运行
- 进去工程目录(有dockerfile)的目录,右键打开Powershell窗口
编译 docker build -t test:v1 .
-t test test是镜像名字
:v1 表示这个镜像的v1版本
- 开始编译界面
- build好之后
- 运行起来
运行 docker run -p 8080:8080 --name test-hello test:v1
--name 容器起名叫test-hello
test:v1 指定是test的镜像,版本号是v1
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
(这里表示端口号冲突了,8080已经被被使用)
这里表示已经有同名字的容器了(这里没加-d参数,表示在前台运行,窗口关了就关了)
- 打开页面测试(点开容器可以看到日志)
- 可以看到实际端口是8080,暴露到外面的端口是9090
- 命令参考文档
传送门
4)docker编译指令说明
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
--dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h "mars": 指定容器的hostname;
-e username="ritchie": 设置环境变量;
--env-file=[]: 从指定文件读入环境变量;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
--link=[]: 添加链接到另一个容器;
--expose=[]: 开放一个端口或一组端口;
--volume , -v: 绑定一个卷
四、目录挂载
1)之前制作镜像之后存在的问题
- 问题
(1)使用 Docker 运行后,我们改了项目代码不会立刻生效,需要重新build和run,很是麻烦。
(2)容器里面产生的数据,例如 log 文件,数据库备份文件,容器删除后就丢失了。 - 解决方法
目录挂载解决以上问题
2)几种挂载方式
- 挂载方式
(1)bind mount (指向宿主机)
直接把宿主机目录映射到容器内,适合挂代码目录和配置文件。可挂到多个容器上
(2)volume (指向docker的·一个区域)
由容器创建和管理,创建在宿主机,所以删除容器不会丢失,官方推荐,更高效,Linux 文件系统,适合存储数据库数据。可挂到多个容器上
(3)tmpfs mount (基本没啥用,指向内存)
适合存储临时文件,存宿主机内存中。不可多容器共享。 - 文档参考
https://docs.docker.com/storage/
3)挂载演示
- 示例
docker run -p 9090:8080 --name test-hello -v D:/code:/app -d test:v1
/code是宿主机的绝对路径
/app 是容器内的目录
-d test:v1 挂载test镜像,版本是v1
- 结果界面
- 这时候修改项目代码,用cat去看刚刚js代码的修改的地方,cat可以看出来同步过去了(
代码更新需要重启下容器
)
(点击这个按钮进入容器里面) - 注释
bind mount 方式用绝对路径 -v D:/code:/app
1)用绝对路径挂载
volume 方式,只需要一个名字 -v db-data:/app
1)只需要名字就可以挂载
- 注意点(
“Error: Cannot find module ‘koa’”
)
因为挂载后,容器里的代码就会替换为你本机的代码了,如果你代码目录没有node_modules目录,你需要在代码目录执行下npm install --registry=https://registry.npm.taobao.org确保依赖库都已经安装,否则可能会提示“Error: Cannot find module ‘koa’”
(如果你的电脑没有安装 nodejs,你需要安装一下才能执行上面的命令。)
五、多容器通信
1)学习目标
项目往往都不是独立运行的,需要数据库、缓存这些东西配合运作。这节我们把前面的 Web 项目增加一个 Redis 依赖,多跑一个 Redis 容器,演示如何多容器之间的通信。
2)创建虚拟网络
- 目的
要想多容器之间互通,从 Web 容器访问 Redis 容器,我们只需要把他们放到同个网络中就可以了。 - 文档参考
传送门
3)演示
(1)创建一个名为test-net的网络:
docker network create test-net
(2)运行 Redis 在 test-net 网络中,别名redis
docker run -d --name redis --network test-net --network-alias redis redis:latest
1)重新运行redis,指定网络
--network test-net
2)给网络起别名叫redis
--network-alias redis
3)用最新的redis版本
redis:latest
4)后台运行
run -d
5)指定容器名字redis
--name redis
(3)修改代码中访问redis的地址为网络别名
- 解除注释
(4)运行 Web 项目,使用同个网络(之前启动过了,现在重新跑下项目指定下网络
)
docker run -p 8080:8080 --name test -v D:/test:/app --network test-net -d test:v1
1)test:v1
镜像用test 的v1版本
- 访问后打印日志
- 访问redis(访问一次自增1,访问3此变成3)
(5)查看数据(访问redis这个变量看是否在自增)
http://localhost:8080/redis
容器终端查看数据是否一致
- 补充相关命令
docker ps 查看当前运行中的容器
docker images 查看镜像列表
docker rm container-id 删除指定 id 的容器
docker stop/start container-id 停止/启动指定 id 的容器
docker rmi image-id 删除指定 id 的镜像
docker volume ls 查看 volume 列表
六、Docker-Compose
1)现存问题
- 问题
在上节,我们运行了两个容器:Web 项目 + Redis
如果项目依赖更多的第三方软件,我们需要管理的容器就更加多,每个都要单独配置运行,指定网络。(单独配置太麻烦) - 接下来(打包配置)
这节,我们使用 docker-compose 把项目的多个服务集合到一起,一键运行。
2)安装docker compose
- 注意点
1)如果你是安装的桌面版 Docker,不需要额外安装,已经包含了。
2)如果是没图形界面的服务器版 Docker,你需要单独安装 安装文档 - 举例安装过程
Install using the repository
1)centosanzhuang1
sudo yum update
sudo yum install docker-compose-plugin
2)确认docker版本
docker compose version
3)更新compose(centos)
sudo yum update
sudo yum install docker-compose-plugin
-------------------------------
安装docker客户端
1) DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
2)修改运行权限
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
所有人加权限
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
3)测试是否安装
docker compose version
3)运行docker-compose检查是否安装成功(打印文档)
3)编写docker-compose.yml文件,描述依赖哪些服务(默认使用同一个网络)
- 参考文档
传送门 - 编写举例
version: "3.7"
--版本号
services: --表示需要哪些服务
app: --第一个需要的服务是app
build: ./ --app是直接从这个工程build
ports: --把容器内8080端口暴露出来当成80端口用
- 80:8080
volumes: --挂载目录是把当前目录挂载到/app目录
- ./:/app
environment: --指定时区(不指定时区默认北京时间)
- TZ=Asia/Shanghai
redis: --第二个需要的是redis
image: redis:5.0.13 --这里使用redis的镜像,已经build好
volumes: --把容器内的/data挂载上去
- redis:/data
environment: --指定时间
- TZ=Asia/Shanghai
volumes:
redis:
4)跑起来
在docker-compose.yml 文件所在目录,执行:
docker-compose up //就可以跑起来了。
命令参考:https://docs.docker.com/compose/reference/up/
- 其他指令
在后台运行只需要加一个 -d 参数docker-compose up -d
查看运行状态:docker-compose ps
停止运行:docker-compose stop
重启:docker-compose restart
重启单个服务:docker-compose restart service-name
进入容器命令行:docker-compose exec service-name sh
查看容器运行log:docker-compose logs [service-name]
七、发布和部署
1)镜像仓库(存储build出来的安装包)
- 镜像仓库介绍
镜像仓库用来存储我们 build 出来的“安装包”,Docker 官方提供了一个 镜像库,里面包含了大量镜像,基本各种软件所需依赖都有,要什么直接上去搜索。 - docker官网提供的镜像库
传送门 - 镜像仓库作用
我们也可以把自己 build 出来的镜像上传到 docker 提供的镜像库中,方便传播。
当然你也可以搭建自己的私有镜像库,或者使用国内各种大厂提供的镜像托管服务,例如:阿里云、腾讯云
2)上传镜像
(1)先注册个账号
传送门 (2)创建个镜像库
(3)命令行登录账号:(输入账号和密码)
docker login -u username
(4)新建一个tag,名字必须跟你注册账号一样()
docker tag test:v1 username/test:v1
(5)推上去
docker push username/test:v1
(6)部署试下
docker run -dp 8080:8080 username/test:v1
(这里没有起名字)
(7)docker-compose 中也可以直接用这个镜像了
version: "3.7"
services:
app:
# build: ./ 这个去掉换成image(镜像)
image: helloguguji/test:v1
ports:
- 80:8080
volumes:
- ./:/app
environment:
- TZ=Asia/Shanghai
redis:
image: redis:5.0.13
volumes:
- redis:/data
environment:
- TZ=Asia/Shanghai
volumes:
redis:
3)阿里云容器托管
docker 官方的镜像托管有时候上传和下载
都太慢了,如果你想要更快的速度,可以使用阿里云的免费镜像托管
这里操作都差不多
八、备份和迁移数据
1)迁移方式介绍
- (1)如果你是用bind mount:
直接把宿主机的目录挂进去容器,那迁移数据很方便,直接复制目录就好了
- (2)如果你是用volume方式挂载:
由于数据是由容器创建和管理的,需要用特殊的方式把数据弄出来。
2)备份和导入Volume的流程
- 1、备份:
1)运行一个 ubuntu 的容器,挂载需要备份的 volume 到容器,并且挂载宿主机目录到容器里的备份目录。
2)运行 tar 命令把数据压缩为一个文件
3)把备份文件复制到需要导入的机器
- 2、导入
1)运行 ubuntu 容器,挂载容器的 volume,并且挂载宿主机备份文件所在目录到容器里
2)运行 tar 命令解压备份文件到指定目录
3)备份MongoDB的数据演示
- 流程
1)运行一个 mongodb,创建一个名叫mongo-data的 volume 指向容器的 /data 目录
docker run -p 27018:27017 --name mongo -v mongo-data:/data -d mongo:4.4
注意这里:
-v mongo-data 表示volume叫mono-data,挂载在容器的/data目录
-d 表示后台运行
mongo:4.4 表示用的是芒果的4.4版本打开docker看volume
打开芒果,插入某个明文数据
2)运行一个 Ubuntu 的容器,挂载mongo容器的所有 volume,映射宿主机的 backup 目录到容器里面的 /backup 目录,然后运行 tar 命令把数据压缩打包
docker run --rm --volumes-from mongo -v C:\Users\kachi\Desktop\backup:/backup ubuntu tar cvf /backup/backup.tar /data/
--rm 表示同名则删除之前的容器
--volumes -from mongo 从芒果这个容器里面挂载volume
-v 指定了绝对路径
ubuntu 镜像使用ubuntu的
tar 用tar压缩/data/目录,命名为/backup/backup.tar
①创建个backup目录
②输入命令
③删除芒果db
④删除数据盘的内容
3)最后你就可以拿着这个 backup.tar 文件去其他地方导入了。
4)恢复 Volume 数据演示
运行一个 ubuntu 容器,挂载 mongo 容器的所有 volumes,然后读取 /backup 目录中的备份文件,解压到 /data/ 目录
docker run --rm --volumes-from mongo -v d:/backup:/backup ubuntu bash -c "cd /data/ && tar xvf /backup/backup.tar --strip 1"
bash -c 执行xxx的脚本路径
tar 解压文件
--strip 1 过滤一些符号信息和调试信息