什么是Docker
Docker 是一种容器化平台和工具,用于构建、部署和运行应用程序和服务。它的主要目标是简化应用程序的部署和管理,提供一种轻量级、可移植、可扩展的容器化解决方案
- 可移植:能指定运行环境,如操作系统(windows/mac/linux),node版本等等。因此项目能方便的跨平台部署。
- 隔离:docker中的镜像运行在docker的容器内,与宿主机几乎完全隔离,容器内的环境与运行时产生的报错不会影响宿主机。但并不是完全隔离,如容器占用cpu过高等,或容器占用磁盘空间较大等等也会影响宿主机。
- 安全性: Docker 提供了一系列安全性功能,包括容器隔离、命名空间、安全策略等,以保护容器内的应用程序和数据。
docker中的一些基本概念
-
镜像(Image)
- 镜像一般由Dockerfile定义,也可以从DockerHub或其他镜像仓库中获取。一般是与部署的代码相关的不可变的容器模版,包含了应用程序和其依赖的文件系统快照、运行时环境和启动命令。
- 创建镜像命令行示例:进入到包含
dockerfile文件的文件夹中,运行
docker build --build-arg resourceDir=${RESOURCE_DIR} -t myApp:1.0 .上述命令意思是,以当前目录(最后的
.)创建容器名为myApp:1.0的容器,并为dockerfile传入变量resourceDir。该变量可以在dockerfile中使用,如在dockerfile中输入COPY ${resourceDir} .- 如果要以远程仓库创建镜像,则运行,即讲最后的
.替换成仓库地址
docker build -t myapp:1.0 https://github.com/myuser/myapp.git/xxxx -
容器(container)
- 是镜像的运行实例,可以理解可快速创建的虚拟机,与宿主机数据隔离,拥有自己的文件系统、网络和进程空间。
-
- Dockerfile 是一个文本文件,包含了一系列指令,用于定义如何构建一个 Docker 镜像。
- Dockerfile 包括基础镜像选择、应用程序代码复制、依赖安装、环境配置等。
- 改文件的一些常用指令
- ARGS 用于初始化一些命令,是唯一能写在FROM之前的指令,用法如:
ARG NODE_VERSION=19.5.0 FROM node:${NODE_VERSION}-alpine - FROM 用于确定镜像的基本环境,如
node/python/nginx版本、操作系统等,也可以用于指定镜像。一个Dockerfile的开头只能是ARGS或者FROM。每一个FROM都意味着一个构建阶段,可以在一个文件里输入多个阶段
FROM [--platform=<platform>] <image> [AS <name>]
# 指定node版本 FROM node:14-alpine as builder # 指定nginx版本 FROM nginx:1.21-alpine # 使用自定义的基础镜像,该镜像包含了 Node.js 14 和 Nginx 1.21 FROM my-custom-image:latest as builder-
ENV 用于设置环境变量,比如常见的
NODE_ENV:ENV NODE_ENV production。在前端项目的dockerfile中,ENV的变量与package.json中通过cross-env设置的变量的一样的。当然,只有同名时是一样的,因为Dockerfile的env本身是针对容器,cross-env是针对node程序。如:// package.json { "scripts":{ "start":"cross-env MY_NAME=mgh webpack-dev-server" } } // Dockerfile ... ENV MY_NAME=mgh -
RUN 通常用于执行一些在镜像构建期间必要的操作,比如安装软件包、执行配置命令、下载文件等。这些操作在镜像构建时只执行一次。例如前端中,打包一个dist一般是构建镜像的过程,可以在
RUN中执行node模块安装等步骤 除此之外,RUN命令还提供了其他选项- -mount
- -network
- -security
-
CMD
CMD在镜像构建时不执行任何操作,但在构建容器时执行。例如,前端中打包一个dist文件夹是一个构建镜像的过程,这段时间内的指令应该用RUN;构建dist后部署配置nginx类似于利用镜像生成容器的过程,配置nginx需要用CMD。另外,如果有多个CMD指令,只有最后一个会生效。 -
EXPOSE 用于指定镜像对外暴露的端口。
-
可以指定端口与暴露的协议
(TCP/UDP),默认是TCP -
下面例子中,容器暴露了端口
3000,而宿主机通过端口1234访问容器内的内容。即在宿主机通过localhost:1234访问容器内部的localhost:3000
-
在通过镜像生成容器时,可以通过// 这里的3000端口,其实就是npm依赖serve的默认端口 ... EXPOSE 3000 // EXPOSE 3000/tcp 与上面一样的效果 ... # Start the app using serve command CMD [ "serve", "-s", "build" ]-p参数制定宿主机的访问接口
docker run my-images -p 1234:3000 - ARGS 用于初始化一些命令,是唯一能写在FROM之前的指令,用法如:
harbor与rancher
harbor
类似于dockerHub,是一个用于存储和管理镜像image的仓库。
部署项目的时候,可以将本地文件打包成镜像,然后将其push到私有的harbor(或者dockerHub中)
实际项目中,可以编写build_image.sh,用于生成镜像和推送镜像
目录结构如下
.
├── Dockerfile
└── build_image.sh
build_image.sh脚本
#!/usr/bin/env bash
set -e # 有错误就立即终止
HARBOR_REGISTRY='harbor-registry.xxxxx.com/tetris' # harbor仓库地址
service=editor-front
if [[ $# -lt 1 ]]; then
mode=test
else
mode=$1
fi
tag=`git rev-parse --short HEAD` # 拿git commitId
cur_dir=`dirname $0` # 当前目录
# 打印信息,即将构建的镜像名
echo building image ${HARBOR_REGISTRY}/${service}: "\x1b[31;42m${tag}\x1b[m"
# 用指定的dockerfile生成镜像,并制定镜像名。
docker build --progress=plain -t ${HARBOR_REGISTRY}/${service}:${tag} -f ${cur_dir}/Dockerfile ${cur_dir}/.. --build-arg mode=${mode}
# 推送镜像到harbor仓库
docker push ${HARBOR_REGISTRY}/${service}:${tag}
Dockerfile内容,这里已经打包出了一个dist文件夹,dockerfile将这个dist文件夹内容打包成镜像,并通过http-server启动本地服务
# 注意这里的`--platform=linux/amd64`,在rancher部署时,发现苹果芯片打包出来会报错,因此额外指定了platform
FROM --platform=linux/amd64 node:16.20-alpine as run
RUN npm config set registry https://nexus3.xxxx.com/repository/npm-all/ \
&& npm install --global http-server
WORKDIR /
COPY /dist .
CMD ["http-server", "-d false", "-s"]
最终,能在本地获得一个镜像,并在远端harbor仓库看到该镜像
如果要在本地运行该镜像,可以执行命令
#这里的-p用于指定本地端口和容器端口映射。http-server启动的服务默认是8080端口
#这时本地访问localhost:5678就能访问部署的内容了
docker run -p 5678:8080 harbor-registry.xxxxx.com/tetris/editor-front:c8c6d62
rancher
Rancher是一个开源的容器管理平台,用于管理容器化的应用程序和基础设施
一般与harbor搭配使用,在新建的任务中,右下角的Image可以修改用于部署的镜像地址
未完待续...