2023-01-30 | 学习笔记 | UNLOCK | 更新时间:2023-1-30 9:45

Docker的快速入门的学习笔记

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化,可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化

安装下载

此为 4.16.2 版本时候编辑的文章

官网:https://www.docker.com/

下载并安装 Docker;

概念介绍

Docker 有三个重要的概念,镜像(image),容器(container),仓库(repository)。容器比作轻量的服务器,那么镜像就是创建它的模版

示例代码

项目结构

docker-demo
|——index.html
|——Dockerfile

index.html
<!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>
Dockerfile
# 基于官方 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

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 忽略文件

.dockerignore
node_modules

通过SCP将dockerignore复制到服务器上

scp ./.dockerignore root@118.89.244.45:/root

本地项目创建 index.js

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的架构版本。