前端进阶之路-docker实战前后端项目部署

1,368 阅读9分钟

d4628535e5dde71124fc916c018886129c1661eb.jpeg

核心组成

Docker 中有三个核心概念:Image、Container、Repository。

  • Image: 有领“好人卡”倾向的广大程序猿一定对 镜像 的概念不会陌生。但和 windows 的那种 iso 镜像相比,Docker 中的镜像是分层的,可复用的,而非简单的一堆文件迭在一起(类似于一个压缩包的源码和一个 git 仓库的区别)。
  • Container: 容器的存在离不开镜像的支持,他是镜像运行时的一个载体(类似于实例和类的关系)。依托 Docker 的虚拟化技术,给容器创建了独立的端口、进程、文件等“空间”,Container 就是一个与宿机隔离 “容器”。容器可宿主机之间可以进行 port、volumes、network 等的通信。
  • Repository: Docker 的仓库和 git 的仓库比较相似,拥有仓库名、tag。在本地构建完镜像之后,即可通过仓库进行镜像的分发。常用的 Docker hub 有 hub.docker.com/cr.console.aliyun.com/ 等。

应用场景

  • Web 应用的自动化打包和发布。
  • 自动化测试和持续集成、发布。
  • 在服务型环境中部署和调整数据库或其他的后台应用。
  • 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。

Docker安装

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了

Windows Docker安装

Docker 并非是一个通用的容器工具,它依赖于已存在并运行的 Linux 内核环境。

Docker 实质上是在已经运行的 Linux 下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的 Linux 主机。

因此,Docker 必须部署在 Linux 内核的系统上。如果其他系统想部署 Docker 就必须安装一个虚拟 Linux 环境。

在 Windows 上部署 Docker 的方法都是先安装一个虚拟机,并在安装 Linux 系统的的虚拟机中运行 Docker。

以Win10 系统为例

Docker Desktop 是 Docker 在 Windows 10 和 macOS 操作系统上的官方安装方式,这个方法依然属于先在虚拟机中安装 Linux 然后再安装 Docker 的方法。

Docker Desktop 官方下载地址: hub.docker.com/editions/co…

注意: 此方法仅适用于 Windows 10 操作系统专业版、企业版、教育版和部分家庭版!

image.png

检查运行WSL2 docs.microsoft.com/zh-cn/windo…

安装完毕,通过 docker version 查看安装版本信息

image.png

MacOS Docker安装

macOS 我们可以使用 Homebrew 来安装 Docker。

Homebrew 的 Cask 已经支持 Docker for Mac,因此可以很方便的使用 Homebrew Cask 来进行安装:

brew install --cask --appdir=/Applications docker

CentOS Docker安装

Docker 支持以下的 64 位 CentOS 版本:

  • CentOS 7
  • CentOS 8
  • 更高版本... 使用官方安装脚本自动安装 安装命令如下:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

也可以使用国内 daocloud 一键安装命令:

curl -sSL https://get.daocloud.io/docker | sh

Docker 镜像加速

国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如:

当配置某一个加速器地址之后,若发现拉取不到镜像,请切换到另一个加速器地址。国内各大云服务商均提供了 Docker 镜像加速服务,建议根据运行 Docker 的云平台选择对应的镜像加速服务。

阿里云镜像获取地址:cr.console.aliyun.com/cn-hangzhou…,登陆后,左侧菜单选中镜像加速器就可以看到你的专属地址了:

image.png

Win10 / MacOS Docker 镜像加速

点击Docker Desktop, 然后点击 Settings,打开配置窗口后左侧导航菜单选择 Daemon。在 Registrymirrors 一栏中填写加速器地址 hub-mirror.c.163.com/  ,之后点击 Apply 保存后 Docker 就会重启并应用配置的镜像地址了

image.png

Docker Hello-world

现在我们准备运行hello-world

方法1:远程 hello-world镜像

docker pull hello-world 

docker run hello-world

image.png

方法2:用Node写一个hello world程序,然后在容器里跑起来

  • 创建 docker-demo文件夹
  • 创建 demo.js,并在demo.js里编写代码 console.log('来自docker容器里运行的 hello world')
  • 编写 Dockerfile文件,并写入以下代码
FROM node:16.11.1-slim
COPY . ./demo
WORKDIR /demo
CMD node demo.js
  • 进入docker-demo目录,在命令行工具中运行 docker image build -t demo .
  • docker images 查看镜像列表
  • docker container run demo

image.png

Docker 常用命令

查看Docker构成及版本

docker version

列出所有镜像

docker image ls  或 docker images

从仓库拉取镜像

docker pull node

完整命令写法如下:

docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

推送镜像到远程仓库

docker push [OPTIONS] NAME[:TAG]

OPTIONS说明:

  • --disable-content-trust : 忽略镜像的校验,默认开启

举栗

docker push demo:v1

运行镜像

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS说明:

  • -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: 绑定一个卷

使用本地镜像 demo 以交互模式启动一个容器,在容器内执行/bin/bash命令。

docker run -it demo /bin/bash

使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为myng。

docker run --name myng -d nginx:latest

使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。

docker run -P -d nginx:latest

使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。

docker run -p 80:80 -v /data:/data -d nginx:latest

绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.1 的 80 端口上。

docker run -p 127.0.0.1:80:8080/tcp ubuntu bash

使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。

docker run -it nginx:latest /bin/bash

删除镜像

# image_name表示镜像名,image_id表示镜像id 
docker image rm image_name/image_id

或

docker rmi image_name/image_id

查看所有容器

docker container ls

或

docker ps

启动容器

启动容器有两种方式,一种是我们前面已经介绍过的,使用docker run命令通过镜像创建一个全新的容器

docker run hello-world

另外一种启动容器的方式就是启动一个已经停止运行的容器:

# container_id表示容器的id
docker start container_id

停止正在运行的容器

docker container stop container_id
或
docker stop container_id

进入容器

# command 为linux命令, eg: /bin/bash
docker exec -it container_id  command

删除容器

删除某个容器,请先用 docker ps 查看容器id

docker rm container_id

删除所有容器

docker rm $(docker ps -q)

删除所有退出的容器

docker container prune

登录登出

登录

docker login -u 用户名 -p 密码

登出 Docker Hub

docker logout

从Docker Hub查找镜像

docker search [OPTIONS] TERM

OPTIONS说明:

  • --automated : 只列出 automated build类型的镜像;
  • --no-trunc : 显示完整的镜像描述;
  • -f <过滤条件>: 列出收藏数不小于指定值的镜像。

举栗

docker search -f stars=10 node

image.png

容器与主机之间copy文件

docker cp : 用于容器与主机之间的数据拷贝。 语法如下

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

OPTIONS说明:

  • -L : 保持源目标中的链接

举栗

主机文件拷贝进容器

将windows主机下的docker-demo目录下的文件test.txt拷贝仅 容易的/demo目录下, 其中d5e7e5080b47为对应的容器ID

docker cp D:\\docker-demo\\test.txt d5e7e5080b47:/demo

image.png

将容器文件拷贝到主机 将容器中的demo目录拷贝到主机D:\docker-demo2目录下

docker cp d5e7e5080b47:/demo D:\\docker-demo2

结果如下图

image.png

Visual Studio Code Docker拓展

Docker

image.png

image.png

Remote - Containers

image.png

Docker部署前端项目

Dockerfile最简单配置

FROM nginx:latest
# 设置linux时区为东8区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 将当前项目打包生成的dist文件夹copy到容器的nginx的默认目录
COPY dist/ /usr/share/nginx/html/
# 暴露端口8080
EXPOSE 8080

Dockerfile最佳实践

FROM nginx:latest
# 设置linux时区为东8区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 将当前项目打包生成的dist文件夹copy到容器的nginx的默认目录
COPY dist /usr/share/nginx/html/fe-proj
# 在项目根目录下的nginx个性化配置
COPY default.conf /etc/nginx/conf.d/
# 暴露端口8080
EXPOSE 8080

Docker部署Nodejs项目

Dockerfile

FROM node:8.11.1
# 设置linux时区为东8区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 容器中创建fe-node-proj目录
RUN mkdir -p /fe-node-proj
# 将当前项目所有文件copy到容器的/fe-node-proj目录
COPY . /fe-node-proj
WORKDIR /fe-node-proj
# 全局安装pm2
RUN npm install pm2@4.5.2 -g --registry=https://registry.npmmirror.com
# 安装pm2插件pm2-logrotate
RUN pm2 install pm2-logrotate
# 设置pm2保留的日志文件个数为50个
RUN pm2 set pm2-logrotate:retain 50
# 设置pm2单个日志文件文件大小最大为 30M
RUN pm2 set pm2-logrotate:max_size 30M
# 声明容器中/share/log为匿名卷 (可选。推荐,因为有些情况需要同步pm2日志到宿主机记录起来,方便后续扫描日志到日志平台)
VOLUME /share/log
# 暴露端口8080
EXPOSE 8080
# 容器启动后执行pm2启动服务,这里必须为 pm2-runtime
# pm2-runtime是为Docker容器设计的,它将应用程序置于前台,从而使容器保持运行状态
CMD ["pm2-runtime", "start", "/fe-node-proj/pm2.config.json"]

pm2.config.json

{
    "apps": [
        {
            "name": "fe-node-proj-service",
            "script": "app.js",
            "cwd": "./",
            "instances": 1,
            "error_file": "/share/log/fe-node-proj-service/error.log",
            "out_file": "/share/log/fe-node-proj-service/out.log",
            "log_date_format": "YYYY-MM-DD HH:mm:ss"
        }
    ]
}

那么使用该Dockerfile构建镜像的命令为

# 构建镜像fe-node
docker build -t fe-node
# 运行一个容器并且将当前机器的/log目录绑定到容器的匿名卷中 
docker run -d -it -name fe-node-container -v /log:/share/log fe-node
# 运行一个容器但是不绑定目录到容器的匿名卷,这时候再/var/lib/docker/volumes(不同版本目录不一样)中就会创建一个目录绑定匿名卷
docker run -d -it -name  fe-node-container fe-node

利用docker动态扩容出来的Node服务截图

image.png

image.png