Docker 基础入门:工作流+实践 🐳

312 阅读6分钟

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

项目仓库地址

github项目地址