Docker 基础入门:工作流+实践 🐳
简介
本项目针对刚刚接触 Docker 的新手,讲解 Docker 基本操作,并结合一个实际案例来讲解具体应用。
环境说明
操作系统:MacOS Ventura 13.0
安装 Docker
通过官方网站地址选择对应的操作系统进行安装即可 官方连接
查看 Docker 版本
docker version
安装成功会显示如下信息(MacOS 版)
Client:
Cloud integration: v1.0.35
Version: 24.0.2
API version: 1.43
Go version: go1.20.4
Git commit: cb74dfc
Built: Thu May 25 21:51:16 2023
OS/Arch: darwin/amd64
Context: desktop-linux
Server: Docker Desktop 4.21.1 (114176)
Engine:
Version: 24.0.2
API version: 1.43 (minimum version 1.12)
Go version: go1.20.4
Git commit: 659604f
Built: Thu May 25 21:52:17 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.21
GitCommit: 3dce8eb055cbb6872793272b4f20ed16117344f8
runc:
Version: 1.1.7
GitCommit: v1.1.7-0-g860f061
docker-init:
Version: 0.19.0
GitCommit: de40ad0
创建本地项目
初始化项目
mkdir learn-docker
npm init -y
npm install express
启动简单的服务
创建 app.js 文件
const express = require("express");
const app = express();
const PORT = 3000;
app.get("/", (req, res) => {
res.send("<p>大家好啊!</p>");
});
app.listen(PORT, () => {
console.log("running at 3000 prot");
});
执行 node app.js 启动服务 此时我们可以在 http://localhost:3000/ 访问到我们的内容。
接下来我们使用 Docker 来实现。
创建 Dockerfile 文件
在项目的根目录创建 Dockerfile 文件
FROM node:20-alpine3.17 # 表示我们使用node 20的版本 注意1
WORKDIR /myDocker # 指定我们的工作目录
COPY package.json . # 将 package.json 复制到工作目录 .表示更目录 也就是我们指定的工作目录
RUN npm install # 执行 package.json
COPY . . # 将本地全部文件拷贝到Docker的工作目录 注意2
EXPOSE 3000 # 暴露3000端口 注意3
CMD ["node","app.js"] # 执行启动服务命令
-
注意 1: Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐
-
注意 2:我们这里需要忽略 node_modules 等一些文件的复制
-
注意 3:EXPOSE 3000 只有文档说明作用 不起任何实际作用。实际开启 3000 端口的是 app.js 的内容;而 Dockerfile 里的 EXPOSE 只是让人们知道这个容器使用的是 3000 端口
创建 .dockerignore 文件
前面提到的注意 2 中的事项,我们已经通过 npm install 安装了 node_modules ,所以不需要再复制一遍。
node_modules
Dockerfile
.dockerignore
.git
.gitignore
构建镜像
通过上面的操作我们就可以来构建镜像了。
docker build .
查看镜像
docker images
会看到如下的展示
REPOSITORY TAG IMAGE ID CREATED SIZE
nodejs-image latest 227b17a0a994 About an hour ago 189MB
给镜像取名字 tag
docker tag 227 baituzai/nodejs:v1.0
- 227 是镜像 id 的前 3 位数字
- baituzai/nodejs:v1.0 用户名/镜像名:版本
注意:如果不加版本就是 lasted 建议务必加上
登录并推送 Docker Hub
docker login
# 根据提示输入用户名和密码
# 成功登录后执行
docker push baituzai/nodejs:v1.0
在构建镜像的时候就定义名字 具名镜像 -t
docker build -t my_docker_image_name .
注意:. 表示相对地址
删除本地的镜像
已经存在于 Docker Hub 所以把本地删除
docker rmi -f baituzai/nodejs:v1.0
- rm remove 移除
- i 表示 image 镜像
- f force 强制删除(在使用中的镜像会被删除)
把镜像拉取到本地
docker pull baituzai/nodejs:v1.0 # docker pull 镜像名称
运行镜像
docker run nodejs-image # docker run 镜像名称
这种方式会占用我们的当前命令行窗口,使用 -d 选项使容器在后台运行
docker run -d nodejs-image # docker run -d 镜像名称
查看在运行的容器
docker ps
# or
docker ps -a
-
ps 表示 process status
-
-a 产看全部 包括未运行的容器
端口映射
当我们运行起容器后,想要在本地访问发现是不能成功的,我们需要把 Docker 服务器的端口转发到本地端口才能进行访问。
docker run -d -p 3000:3000 nodejs-image
- 3000:3000 主机端口:容器端口,访问主机端口 3000 的时候就会访问容器端口 3000。使用其他端口也可以,只要不冲突就好。
给这个容器自定义一个名字
如果不定义那么系统就会给容器随机定义一个名字
docker run -d -p 3000:3000 --name nodejs-container nodejs-image
停止运行容器(关机)
把不使用的容器停止运行,也就关机,节省资源。
docker stop nodejs-container # 容器的id 或者是容器的名字都可以
删除容器
docker rm container_id/contanier_name
# 强制删除
docker rm -f container_id/contanier_name
修改本地文件 同步到 docker 文件
修改本地文件后,docker 不会自动同步, 镜像如同一张照片,只修改文件并没有修改镜像,所以需要生成新的镜像
查看我们正在运行的容器
如何访问容器呢?
docker exec -it nodejs-container /bin/sh
- exec ececute 执行
- i interactive 交互
- t pseudo-TTY 伪终端
- nodejs-container 容器名
- /bin/sh 表示我们执行一个新的 bash shell
执行后会直接进入我的工作目录 myDocker
使用 exit 退出 shell
销毁容器
docker rm -f nodejs-container
重新开启一个容器 -v
docker run -d -v /Users/your_name/Desktop/learnDocker/:/myDocker -p 3000:3000 --name nodejs-container nodejs-image
-
绝对路径 本地文件夹路径:容器文件夹路径 (/Users/your_name/Desktop/learnDocker/:/myDocker)
-
本地文件夹路径使用
pwd查看或者使用环境变量
改动后能否成功?
虽然文件内容同步更改了,但是还是不行 因为根据镜像启动容器的时候 使用 node app.js 是根据执行是的服务器文件来启动服务的。
如果文件有修改我们需要重新执行 node app.js 才能显示最新的内容。
使用 nodemon 来自动重启
- 再次删除容器
- 安装 nodemon
npm i nodemon -D
修改 package.json 的脚本
"scripts": {
"dev": "nodemon app.js"
}
修改 Dockerfile
将 CMD ["node","app.js"] 改成 CMD [ "npm","run","dev"]
删除之前的镜像 并重构镜像
使用-v 选项再次启动容器
docker run -d -v /Users/jiajunhua/Desktop/learnDocker/:/myDocker -p 3000:3000 --name nodejs-container nodejs-image
特殊处理
不要同步的文件 node_modules
docker run -d -v /Users/jiajunhua/Desktop/learnDocker/:/myDocker -v /myDocker/node_modules -p 3000:3000 --name nodejs-container nodejs-image
- 说明 ndoe_modules 文件夹不进行同步
容器内容修改也会导致本地内容修改 这不是我们想要的
我们要让本地变成只读模式 readonly 也就是 容器修改不会影响到本地的内容 单项流通
在-v 后面加上冒号 ro :ro
docker run -d -v /Users/jiajunhua/Desktop/learnDocker/:/myDocker:ro -v /myDocker/node_modules -p 3000:3000 --name nodejs-container nodejs-image
使用 volume 时 当删除容器的时候 把对应的 volume 也删除
docker rm -fv nodejs-container
解决每次写命令都很长的问题 docker-compose
touch docker-compose.yml # 创建 docker-compose.yml 文件
version: '3.8'
services:
nodejs-contaier:
build: .
ports:
- "3000:3000"
volumes:
- ./:/myDocker:ro
- /myDocker/node_modules
注意这里的缩进是必要的
启动 docker-compose
docker-compose up
docker-compose up -d # -d 后台运行模式
docker-compose up -d --build # --build 镜像修改后 docker-compose 自动重建
清除 docker-compose
docker-compose down -y