引言
前端掌握Docker要掌握到什么程度呢?其实只要能写DockerFile脚本就行了,至于深入原理和底层啊,看自己兴趣吧。毕竟Go我只会CRUD,反正目前对于我来说足够用了,下面我来介绍一下Docker水文和分享我在项目中如何使用Docker,反正就是简单粗暴
,至于k8s容器编排
,给我直接上腾讯云ok
,毕竟我只是一个切图仔,最复杂我也只会用docker-compose
,那就开始Docker之旅吧
关于install,自己去官网下载Docker桌面端就行了
Docker是什么?
Docker 是一种开源的应用容器引擎,它基于 Golang 语言开发,允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 服务器。Docker 提供了一个供开发人员和系统管理员构建、运行和与容器共享应用程序的平台。使用 Docker 容器部署应用程序被称为容器化。虽然容器并不是新事物,但它们在轻松部署应用程序方面的应用却是新的。
为什么需要Docker?
Docker 的出现主要是为了解决以下问题:“在我的机器上运行正常,但为什么到你的机器上就运行不正常了?”。
例如,你编写了一个 Web 应用,并且在本地调试没有任何问题。然而,当你想让你的朋友试试看,或者想将其部署到远程的云服务器上查看效果时,你首先需要配置和你本地相同的软件环境,包括数据库、Web 服务器(如 IIS,Tomcat,Nginx)以及必要的插件和库等。但这样你仍然不能保证你的软件一定能够运行起来,因为别人可能使用的是完全不同的操作系统,即使是使用 Linux,每种发行版也会有微小的区别。
为了模拟完全相同的本地开发环境,我们首先想到的就是虚拟机。但是,虚拟机需要模拟硬件和运行整个操作系统,不仅体积大,内存占用高,而且程序的性能也会受到影响。
Docker 的优势
Docker和虚拟机的区别
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker
技术比虚拟机技术更为轻便、快捷。
下面的图片比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
特性 | docker容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生(宿主机) | 弱于原生 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
Docker中的重要概念
Docker中的三个重要概念分别是:Image(镜像),Container(容器),Repository(仓储)。
镜像(Image)
Docker 镜像可以被认为是 Docker 容器的 "蓝图"。它包含了运行应用程序所需的所有元素,包括代码、运行时环境、库、环境变量和配置文件。镜像是只读的,容器在运行时创建的任何文件或对现有文件的任何修改都将写入容器的层,而不影响下面的镜像层。
镜像可以从 Dockerfile 创建,Dockerfile 是一个包含了创建镜像所需的指令的文本文件。你可以把 Dockerfile 看作是一个脚本,这个脚本包含了一组用来构建镜像的指令。
镜像还可以从已经存在的容器中创建,如果你对一个容器进行了修改,你可以提交这些修改来创建一个新的镜像。
Docker 中比较出名的镜像有:
- ubuntu: 最流行的 Linux 发行版之一
- alpine: 一个非常小巧(只有 5 MB)的 Linux 发行版,常被用于构建轻量级的 Docker 镜像
- nginx: 一个高性能的 HTTP 和反向代理服务器
- redis: 一个开源的使用 ANSI C 编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库
- mysql: 一个流行的开源关系数据库管理系统
容器(Container)
如果说镜像是静态的 "蓝图",那么容器就可以被认为是这个 "蓝图" 的一个运行实例。你可以启动、停止、删除或者查看容器的状态,也可以进入到一个正在运行的容器中,对其进行操作。
容器在启动时会创建一个可写的层(称为容器层),所有对容器的修改(如文件修改、新文件的创建等)都会写入到这个容器层,这个容器层是存在于镜像层之上的。
Docker 使用了一种称为联合文件系统(Union File System)的技术,允许多个文件系统(在这里是镜像层和容器层)联合挂载到同一个视点,从而形成一个单一的、一致的文件系统。
仓库(Repository)
仓库是存放 Docker 镜像的地方。仓库允许你分享你的镜像,你可以将你的镜像推送(push)到仓库,也可以从仓库拉取(pull)其他人分享的镜像。
Docker 提供了一个公共的仓库 Docker Hub,你可以在 Docker Hub 上找到成千上万的由社区用户分享的镜像。此外,你也可以创建自己的私有仓库。
在企业环境中,为了安全和效率的考虑,通常会搭建私有 Docker 仓库。私有 Docker 仓库可以用来存放企业内部使用的镜像,确保敏感数据不会被外泄,并且可以提高镜像的下载速度。
常用的Docker命令
-
docker run: 用于从 Docker 镜像启动一个容器。例如,
docker run -p 8080:80 -d my-app
将从名为 "my-app" 的 Docker 镜像启动一个新的容器,并将容器的 8080 端口映射到主机的 80 端口。 -
docker build: 用于从 Dockerfile 构建 Docker 镜像。例如,
docker build -t my-app .
将使用当前目录中的 Dockerfile 构建一个名为 "my-app" 的 Docker 镜像。 -
docker pull: 用于从 Docker Hub 或其他 Docker 注册服务器下载 Docker 镜像。例如,
docker pull nginx
将从 Docker Hub 下载官方的 Nginx 镜像。 -
docker push: 用于将 Docker 镜像推送到 Docker Hub 或其他 Docker 注册服务器。例如,
docker push my-app
将名为 "my-app" 的 Docker 镜像推送到你的 Docker Hub 账户。 -
docker ps: 用于列出正在运行的 Docker 容器。添加
-a
选项(docker ps -a
)可以列出所有容器,包括已停止的。 -
docker stop: 用于停止正在运行的 Docker 容器。例如,
docker stop my-container
将停止名为 "my-container" 的 Docker 容器。 -
docker rm: 用于删除 Docker 容器。例如,
docker rm my-container
将删除名为 "my-container" 的 Docker 容器。 -
docker rmi: 用于删除 Docker 镜像。例如,
docker rmi my-app
将删除名为 "my-app" 的 Docker 镜像。 -
docker logs: 用于查看 Docker 容器的日志。例如,
docker logs my-container
将显示名为 "my-container" 的 Docker 容器的日志。 -
docker exec: 用于在正在运行的 Docker 容器中执行命令。例如,
docker exec -it my-container bash
将在名为 "my-container" 的 Docker 容器中启动一个 bash shell。
如何写DockerFile
Dockerfile 是一个用于构建 Docker 镜像的文本文件,它包含了一系列的指令和参数,其实很简单的,会简单的shell脚本,理解DockerFile没有什么难度
# 使用官方 Node.js10镜像
FROM node:10
# 设置工作目录
WORKDIR /usr/src/app
# 将 package.json 和 package-lock.json 复制到工作目录
COPY package*.json ./
# 安装应用程序依赖项
RUN npm install
# 复制应用程序的所有文件到工作目录
COPY . .
# 开放端口 8080 供应用程序使用
EXPOSE 8080
# 定义 Docker 镜像运行的命令
CMD [ "node", "server.js" ]
下面是一些常见的 Dockerfile指令
-
FROM: 这个指令定义了构建新镜像所基于的基础镜像。例如,如果你的应用是一个 Node.js 应用,你可能会使用
FROM node:14
作为你的 Dockerfile 的第一行。FROM node:14
-
WORKDIR: 这个指令用于设置工作目录,或者说,接下来的指令(如 RUN、CMD、COPY、ADD 等)将在哪个目录下执行。
WORKDIR /app
-
COPY: 这个指令将从 Dockerfile 所在的目录中复制文件到镜像中。它有两个参数,源和目标。它通常用于将应用的源代码或应用所需的配置文件复制到镜像中。
COPY . .
-
ADD: 这个指令和 COPY 类似,都是将文件从 Dockerfile 所在的目录复制到镜像中。但是 ADD 更为强大,它允许源文件是一个 URL,或者在复制的过程中可以自动解压缩文件。
-
RUN: 这个指令用于执行任何被后面跟着的命令。这些命令在镜像构建时运行,并且它们的结果将会被包含到镜像中。这通常用于安装软件包。
RUN npm install
-
CMD: 这个指令用于提供默认的可执行命令,这些命令在镜像被运行(即,创建为一个容器)时执行。如果 Docker run 命令行中指定了其他命令,那么 CMD 指令将被忽略。
CMD [ "node", "server.js" ]
-
EXPOSE: 这个指令用于指明在运行时容器监听的端口。
EXPOSE 8080
-
ENV: 这个指令用于设置环境变量。这些变量以
key=value
的形式存在,可以在容器运行时被使用。ENV NODE_ENV=production
-
ENTRYPOINT: 这个指令和 CMD 类似,都是在容器启动时执行的命令,但 ENTRYPOINT 的参数不会被 Docker run 命令行中的参数覆盖,而 CMD 的会。
其它指令去翻翻官方文档就行啦
Docker的分层设计
最后,了解一下Docker比较重要的设计概念
Docker 的分层设计是 Docker 强大功能的关键,这种设计让镜像的创建、复制和部署变得更为高效。
Docker 镜像是由多个只读层组成的。每个层都是前一层的增量更改,每个改变都会生成一个新的层。这种分层设计意味着,当你更改一个 Docker 镜像(比如更新应用程序的一个版本),新的 Docker 镜像只会生成包含更改部分的新层。新镜像其他的部分,比如操作系统或库,都会共享基础镜像的相应层。这使得镜像变得更小,构建更快,并且能更有效地利用磁盘空间。
当 Docker 镜像被运行为 Docker 容器时,Docker 会添加一个读写层到镜像的顶部。所有对运行容器的更改 - 无论是文件系统的修改,还是添加新文件,都会应用到这个可写层。这个读写层也被称为容器层。
Docker 使用 Union File System 来实现这种分层设计。Union File System 允许多个只读文件系统(Docker 的镜像层)与一个可写文件系统(容器层)被合并为一个单一的文件系统视图。这意味着,从容器内部看,所有的文件系统层看起来就像一个普通的、统一的文件系统。
Docker 的分层设计为 Docker 提供了许多强大的特性,包括镜像的快速构建和部署,以及容器之间的高效文件共享。
Docker项目实战
以下是我的编程时光网站的DockerFile文件和shell脚本,分享给大家
DockerFile
FROM nginx
ENV BASE=true
COPY ./dist /usr/share/nginx/html/
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY ./coding-time.cn_bundle.crt /etc/nginx/coding-time.cn_bundle.crt
COPY ./coding-time.cn_bundle.pem /etc/nginx/coding-time.cn_bundle.pem
COPY ./coding-time.cn.key /etc/nginx/coding-time.cn.key
COPY ./coding-time.cn.csr /etc/nginx/coding-time.cn.csr
depoly脚本
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
git pull origin main
npm run docs:build
# 打包docker镜像之前把之前的先删除了 - 这里不用版本号管理了
sudo docker rmi coding-time -f
sudo docker rm coding-time-container -f
# 打包新的镜像
sudo docker build -t coding-time .
sudo docker run -itd -p 443:443 -p 80:80 --name coding-time-container coding-time
nginx配置
server {
#SSL 默认访问端口号为 443
listen 443 ssl;
#请填写绑定证书的域名
server_name www.coding-time.cn;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /etc/nginx/coding-time.cn_bundle.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /etc/nginx/coding-time.cn.key;
ssl_session_timeout 5m;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
location / {
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
#例如,您的网站主页在 Nginx 服务器的 /etc/www 目录下,则请修改 root 后面的 html 为 /etc/www。
root /usr/share/nginx/html; # nginx的静态资源目录
index index.html index.htm;
try_files $uri $uri/ /index.html; # 对于 Vue 或 React项目使用history路由需要
}
}
server {
listen 80;
#请填写绑定证书的域名
server_name www.coding-time.cn;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
error_log /var/log/nginx/error.log error;
location / {
root /usr/share/nginx/html; # nginx的静态资源目录
index index.html index.htm;
try_files $uri $uri/ /index.html; # 对于 Vue 或 React项目使用history路由需要
}
#把http的域名请求转成https
return 301 https://$host$request_uri;
}