Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化
安装下载
此为 4.16.2 版本时候编辑的文章
下载并安装 Docker;
概念介绍
Docker 有三个重要的概念,镜像(image),容器(container),仓库(repository)。容器比作轻量的服务器,那么镜像就是创建它的模版
示例代码
项目结构
docker-demo
|——index.html
|——Dockerfile
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello docker</h1>
</body>
</html>
# 基于官方 nginx 镜像
FROM nginx
# 指定镜像架构为windows版本,主要看你的容器是什么架构的,默认是 linux/arm64
# FROM --platform=windows/arm64 nginx
# 将当前目录下 index.html 替换容器中 /usr/share/nginx/html/index.html 文件
COPY index.html /usr/share/nginx/html/index.html
在示例项目根目录执行以下命令
docker build . -t test-image:latest
docker run -d -p 80:80 –name test-container test-image:latest
build
创建 docker 镜像
.
使用当前目录下的 dockerfile 文件
-t
使用 tag 标记版本
test-image:latest
创建名为 test-image 的镜像,并标记为 latest(最新)版本
run:
创建并运行 docker 容器
-d:
后台运行容器
80:80:
将当前服务器的 80 端口(冒号前的 80),映射到容器的 80 端口(冒号后的 80)
–name:
给容器命名,便于之后定位容器
test-image:latest:
基于 test-image 最新版本的镜像创建容器
镜像管理
# 将本地镜像test-image:latest传到 xianbinli 用户的 docker 仓库上
docker push xianbinli/test-image:latest
# 拉取远程仓库的镜像
docker pull xianbinli/test-image:latest
搭建自动化部署
# Step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils
# Step 2: 添加软件源信息,使用阿里云镜像
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 安装 docker-ce
sudo yum install docker-ce docker-ce-cli containerd.io
# Step 4: 开启 docker服务
sudo systemctl start docker
# Step 5: 运行 hello-world 项目
sudo docker run hello-world
# 安装git环境
yum install git
# 安装NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
# 设置环境变量
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
# 通过NVM 安装node
nvm install node
# 安装PM2:可以运行js脚本
npm i pm2 -g
打开git仓库,可以是GitHub上的,也可以是自己部署的Gitlab,打开仓库的Settings设置
,打开 Webhooks
.点击添加
Payload URL: 填写服务器的公网IP,记得添加 http(s) 前缀
Content type: 选择 application/json 即发送 json 格式的 post 请求
触发时机:Just the push event,即仓库 push 事件,根据不同的需求还可以选择其他事件,例如 PR,提交 Commit,提交 issues 等
当服务器接受到请求后,需要创建或者更新镜像来实现自动部署
在本地项目创建一个 dockerfile
# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
通过SCP将Dockerfile复制到服务器上
scp ./Dockerfile root@118.89.244.45:/root
创建 .dockerignore 忽略文件
node_modules
通过SCP将dockerignore复制到服务器上
scp ./.dockerignore root@118.89.244.45:/root
本地项目创建 index.js
const http = require("http")
const {execSync} = require("child_process")
const path = require("path")
const fs = require("fs")
// 递归删除目录
function deleteFolderRecursive(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file) {
const curPath = path + "/" + file;
if(fs.statSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}
const resolvePost = req =>
new Promise(resolve => {
let chunk = "";
req.on("data", data => {
chunk += data;
});
req.on("end", () => {
resolve(JSON.parse(chunk));
});
});
http.createServer(async (req, res) => {
console.log('receive request')
console.log(req.url)
if (req.method === 'POST' && req.url === '/') {
const data = await resolvePost(req);
const projectDir = path.resolve(`./${data.repository.name}`)
deleteFolderRecursive(projectDir)
// 拉取仓库最新代码
execSync(`git clone https://github.com/yeyan1996/${data.repository.name}.git ${projectDir}`,{
stdio:'inherit',
})
}
// 复制 Dockerfile 到项目目录
fs.copyFileSync(path.resolve(`./Dockerfile`), path.resolve(projectDir,'./Dockerfile'))
// 复制 .dockerignore 到项目目录
fs.copyFileSync(path.resolve(__dirname,`./.dockerignore`), path.resolve(projectDir, './.dockerignore'))
// 创建 docker 镜像
execSync(`docker build . -t ${data.repository.name}-image:latest `,{
stdio:'inherit',
cwd: projectDir
})
// 销毁 docker 容器
execSync(`docker ps -a -f "name=^${data.repository.name}-container" --format="{{.Names}}" | xargs -r docker stop | xargs -r docker rm`, {
stdio: 'inherit',
})
// 创建 docker 容器
execSync(`docker run -d -p 8888:80 --name ${data.repository.name}-container ${data.repository.name}-image:latest`, {
stdio:'inherit',
})
console.log('deploy success')
res.end('ok')
}).listen(3000, () => {
console.log('server is ready')
})
通过SCP将index.js复制到服务器上
scp ./index.js root@118.89.244.45:/root
之后在服务器上运行
pm2 start index.js
上述 demo 只创建了单个 docker 容器,当项目更新时,由于容器需要经过销毁和创建的过程,会存在一段时间页面无法访问情况
而实际投入生产时一般会创建多个容器,并逐步更新每个容器,配合负载均衡将用户的请求映射到不同端口的容器上,确保线上的服务不会因为容器的更新而宕机
目前还没搞服务器,等后面再试试
参考文章:https://juejin.cn/post/6845166890420011021
问题集合
Win10系统启动 Docker 后一直显示 ‘docker desktop starting’
切换到目录 C:\Program Files\Docker\Docker 执行 DockerCli.exe -SwitchDaemon
使用管理员执行Window PowerShell
cd 'C:\Program Files\Docker\Docker'
.\DockerCli.exe -SwitchDaemon
Docker启动失败
管理员执行以下命令
Net stop com.docker.service
Net start com.docker.service
提示 Unable to calculate image disk size
无法计算映像磁盘大小 导致容器不能设置
1: 打开任务管理器,点击性能,CPU 查看虚拟化是否被禁止,需要开启
2:打开控制面板,点击程序,查看window程序的开启,查看Hyper-V
服务以及适用于linuk 的window子系统
服务是否被关闭,需要开启。
3: 重启电脑后,执行以下命令启动 Hyper-V
dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All
提示 Error response from daemon: open \.\pipe\docker_engine_windows: The system cannot find the file specified
参考文章:https://blog.jermdavis.dev/posts/2022/fix-broken-pipe-docker-engine-windows
缺少了 docker_engine_windows 通道,导致执行失败,查看关于docker通道命令,需要使用Window PowerShell执行 get-childitem \\.\pipe\ | where { $_.Name -match "docker_" }
使用管理员执行Window PowerShell
cd 'C:\Program Files\Docker\Docker\resources\'
.\dockerd.exe -G docker-users --config-file c:\programdata\docker\config\daemon.json --register-service
start-service docker
执行docker build 提示 no matching manifest for windows/amd64 10.0.19044 in the manifest list entries
打开Docker控制面板,点击设置中的 Docker Engine
将 experimental: false 改为 true 即可
执行 docker run 提示 WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (windows/amd64) and no specific platform was requested
拉取的镜像版本和当前Docker执行的架构版本不同,需要重新拉取指定版本镜像或者切换Docker的架构版本。