make
工具简化构建docker镜像的过程提高效率。make
是可以用来构建和管理Docker镜像的命令行工具,该工具可以组合不同的指令混合使用。在Mac环境下可以使用brew install make
指令通过homebrew
安装make工具
。go mod tidy
监测并下载项目中缺失的依赖包(实际上go mod tidy的主要作用是清理项目中未使用的依赖,更新go.mod和go.sum文件;当执行go mod tidy
时,go工具链首先会扫描所有的Go文件,分析import声明确认有效的依赖项;然后将go.mod中未被引用的依赖项删除,对缺少的依赖尝试添加,并更新go.sum文件)。依赖包都下载后执行go build -o main .
指令将项目编译成名为main
的可执行文件。golang:alpine
作为基础镜像并将结果命名为builder
,golang:apline
是基于Alpine Linux操作系统的Go镜像,Alpine LInux是一个轻量级的Linux发行版,因此golang:apline
镜像通常比golang
镜像更小、更快。第二阶段也使用了轻量级的alpine
镜像作为基础镜像,并从第一阶段的结果(builder
)中拷贝可执行文件和配置文件。docker build
指令将项目打包成docker镜像,再使用make工具帮助简化构建docker镜像过程。以下是完整的Dockerfile文件和构建过程。# 第一阶段
FROM golang:alpine as builder
# 使用golang:alpine作为基础镜像,并将该阶段/结果命名为builder
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
# 更换alpine linux的软件源为中科大的镜像源
WORKDIR /app
# 设置工作目录
COPY . .
# 拷贝所有文件到工作目录中
ENV GOPROXY=https://goproxy.io
# 设置GOPROXY的环境变量
RUN go mod tidy
# 下载管理项目依赖
RUN go build -o main .
# 编译当前目录下的Go代码,并将可执行文件命名为main
# 第二阶段
FROM alpine:3.10.0
# 使用alpine:3.10.0作为基础镜像
WORKDIR /app
# 设置工作目录 方便在容器中进行操作和管理文件
COPY --from=builder /app/main /app/main
COPY --from=builder /app/config/prod.config.yaml /app/config/config.yaml
# 从builder(第一阶段)目录中的/app/main 复制到当前目录 /app/main
# 从builder目录中的 /app/config/prod.config.yaml文件,复制到/app/config/目录下,并将文件命名为config.yaml
EXPOSE 8085
# 暴露端口8085
CMD ["/app/main","-env","prod"]
# 在容器内执行/app/main命令,并传参 -env prod
-t
参数用于指令镜像名称(basic_project)和标签(v1), .
表示当前目录 (Dockerfile所在目录),也可以通过-f
指定Dockerfile的路径(.
对于-f
指定的Dockerfile而言,就是当前的相对路径,基于当前目录查找指定的Dockerfile)。docker build -t basic_project:v1 .
# or
docker build -f ./Dockerfile -t basic_project:v1 .
伪目标
,即.PHONY:xxx
作为一组指令的标签,下面是指令的名称。@
的作用是不将执行的指令打印到屏幕中。使用Make工具就几件事,重新构建镜像时把之前的可执行文件删掉,将之前的镜像删掉,重新构建镜像。.PHONY: docker
docker:
# 清理上次编译的可执行文件main,如果main不存在则返回一个错误,|| true会让程序继续往下运行
@rm main || true
# docker删除镜像 basic_project:v1
@docker rmi -f basic_project:v1
# docker构建镜像
@docker build -t basic_project:v1 .
.PHONY: clean
clean:
@rm main || true
@echo "clean success"
使用make docker
指令构建镜像
make docker
name: "basicproject"
mode: "dev"
port: 8085
version: "v0.0.1"
mysql:
host: "your_ip" // 你的电脑ip地址
port: 3306
user: "root"
password: "12345678"
dbname: "testdb"
max_open_conns: 200
max_idle_conns: 50
redis:
host: "your_ip" // 你的电脑ip地址
port: 6379
basic_project
,数据库Mysql
和Redis
。因为Docker-compose共享网络的关系,可以将项目中config.yaml
文件中的数据库ip地址配置为services
中定义数据库的名称。修改完配置文件后要记得重新打包镜像。name: "basicproject"
mode: "prod"
port: 8085
version: "v0.0.1"
mysql:
host: "db" # docker-compose.yaml文件中services中定义的db
port: 3306
user: "root"
password: "12345678"
dbname: "testdb"
max_open_conns: 200
max_idle_conns: 50
redis: # docker-compose.yaml文件中 services中定义的redis
host: "redis"
port: 6379
version: '3.7' # Docker Compose版本号 3.7
services: # 定义服务
db: #定义MySQL服务
image: 'mysql:8.0' # 指定镜像文件
container_name: 'basic-project-mysql' # 容器名称
command: --default-authentication-plugin=mysql_native_password
#设置MySQL的默认认证插件为mysql_native_password
environment:
# 设置Mysql数据库的root密码和数据库名称
MYSQL_ROOT_PASSWORD: 12345678
MYSQL_DATABASE: testdb
# 要确保要挂载的目录存在且有正确的读取权限
volumes:
- /var/lib/mysql
ports:
# 3306端口映射13306端口
- '13306:3306'
redis: #定义redis服务
image: 'redis:7.2.3'
container_name: 'basic_project_redis'
ports:
- '16379:6379'
backend: # 定义后端服务
depends_on: #指该服务依赖其他服务,确保redis和db这两个服务启动运行正常再启动backend服务
- redis
- db
image: 'basic_project:v1'
container_name: 'basic-project'
ports:
- '8085:8085'
restart: always # 设置重启
docker-compose up -d
CONTROL PLANE
和Node
组成。CONTROL PLANE
由kube-api-server
、Kube-scheduler
、Kube-controller-manager
、etcd
和cloud-controller-manager
组成,控制平面组件会为集群做出全局决策,如资源的调度,检测和相应集群事件。控制平面组件可以在集群中的任何节点上运行,但为了方便通常会在同一台计算机上启动所有控制平面组件,并且不会在此计算机上运行用户容器。kube-api server
是k8s控制平面的前端,负责处理请求工作;etcd
是一致且高可用的键值存储,用于K8s所有集群数据的后台数据库。kube-scheduler
负责监控新创建、未指定运行节点(Node)的Pods,并选择节点让Pod在上面运行。kube-controller-manager
负责运行控制器进程。Node
是一群工作节点。kubelet
会在集群中的每个节点(node)上运行,保证容器都运行在Pod中。kube-proxy
是集群每个节点上运行的网络代理。可以在https://kubernetes.io/docs/tasks/tools/
安装kubectl
工具。我的环境是Apple Silicon
的Mac环境,使用下面这条指令安装。
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
1. PersistentVolume
是集群中的一块存储空间,用于存储数据库文件,PV可以是网络文件系统、云存储、本地存储;
2. PersistentVolumeClaim
是用户对存储的请求。用户可以在PVC中指定所需的存储大小和访问模式(读写权限),k8s会找一个满足这些条件的PV并挂在到Pod上。如果找不到则动态创建一个。
3. Deployment
是一种高级的Pod管理策略,它可以确保任何时候都有指定数量的Pod运行。Deploymen会创建ReplicaSet来保证Pod的数量;
4. Service
是一种抽象,它定义了访问一组 Pod 的策略。因为 Pod 可能会频繁地创建和销毁,所以它们的 IP 地址可能会经常变化。Service 通过选择器来选择一组 Pod,并为它们提供一个稳定的 IP 地址和 DNS 名称,这样其他的 Pod 就可以通过这个 IP 地址或 DNS 名称来访问这组 Pod。
# Service 提供一个稳定的接口来访问Mysql
# 定义资源的版本和类型
apiVersion: v1
# 定义资源的类型
kind: Service
# 定义资源的名称
metadata:
name: basic-project-mysql
# 定义资源的规格、内容
spec:
type: LoadBalancer # 为了方便调试
# 定义端口
ports:
# 服务的端口号
- port: 3309
# 名称
name: mysql
# 服务的协议,通常是TCP
protocol: TCP
# Pod上的目标端口
targetPort: 3306
# selector 定义了哪些Pod可以被此Server访问,通常是通过标签选择器实现的
selector:
app: basic-project-mysql
---
# Deployment 定义Pod的规格
# 定义资源的版本
apiVersion: apps/v1
# 定义资源的类型
kind: Deployment
# 定义资源的名称和标签
metadata:
name: basic-project-mysql
# 定义资源的规格
spec:
# 定义那些Pod可以被Deployment管理
replicas: 1
# 指定Pod的副本数量。如果没有指定那么默认是1
selector:
matchLabels:
app: basic-project-mysql # 选择器 用于找到要管理的pod
template: # Pod的模板
metadata:
labels:
app: basic-project-mysql
spec:
containers:
- name: mysql-8
env:
- name: MYSQL_ROOT_PASSWORD # 图方便但不安全 设置用户名跟密码
value: "12345678"
- name: MYSQL_DATABASE
value: "testdb"
image: mysql:8.0 #使用的Docker镜像
ports:
- containerPort: 3306 # 容器端口号
name: mysql
volumeMounts: # 挂载volume到容器的文件系统
- mountPath: /var/lib/mysql # 挂载路径
name: mysql-storage
volumes: # 定义volume
- name: mysql-storage
persistentVolumeClaim: # 使用PersistentVolumeClaim作用volume的源
claimName: basic-project-mysql-pv-claim
# PersistentVolumeClaim 用于声明对PersistentVolume的需求
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: basic-project-mysql-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce # 表示volume可以被一个Pod读写
resources:
requests:
storage: 1Gi #请求1GB的存储空间
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: basic-project-mysql-pv-claim
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
❯ kubectl apply -f k8s-basicproject-mysql.yaml
service/basic-project-mysql unchanged
deployment.apps/basic-project-mysql configured
persistentvolumeclaim/basic-project-mysql-pv-claim unchanged
persistentvolume/basic-project-mysql-pv unchanged
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
basic-project-mysql-758785bcd5-mqrvm 1/1 Running 0 9m15s
# Service
apiVersion: v1
kind: Service
metadata:
name: basic-project-redis
spec:
type: LoadBalancer
ports:
- port: 16379
name: redis
protocol: TCP
targetPort: 6379
selector:
app: basic-project-redis
# Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: basic-project-redis-deployment
spec:
replicas: 1
selector:
matchLabels:
app: basic-project-redis
template:
metadata:
labels:
app: basic-project-redis
spec:
containers:
- name: redis
image: redis:7.2.3
ports:
- containerPort: 6379
❯ kubectl apply -f k8s-basicproject-redis.yaml
service/basic-project-redis configured
deployment.apps/basic-project-redis-deployment configured
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
basic-project-mysql-758785bcd5-mqrvm 1/1 Running 0 34m
basic-project-redis-deployment-7db758f6b5-h88bg 1/1 Running 0 4s
name: "basicproject"
mode: "prod"
port: 8086
version: "v0.0.1"
mysql:
host: "your_ip"
port: 3309
user: "root"
password: "12345678"
dbname: "testdb"
max_open_conns: 200
max_idle_conns: 50
redis:
host: "your_ip"
port: 16379
apiVersion: v1
kind: Service
metadata:
name: basic-project
spec:
type: LoadBalancer
selector:
app: basic-project
ports:
- name: http
port: 8086
protocol: TCP
targetPort: 8086
---
apiVersion: apps/v1
kind : Deployment
metadata:
name: basic-project
spec:
replicas: 1
selector:
matchLabels:
app: basic-project
template:
metadata:
labels:
app: basic-project
spec:
containers:
- name: basic-project
image: basic_project:v1
ports:
- containerPort: 8086
❯ kubectl apply -f k8s-basicproject-backend.yaml
service/basic-project unchanged
deployment.apps/basic-project configured
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
basic-project-679b8d4849-8hdwj 1/1 Running 0 11m
basic-project-mysql-7995c97fd6-gggnm 1/1 Running 1 (75m ago) 143m
basic-project-redis-deployment-7db758f6b5-h88bg 1/1 Running 1 (75m ago) 170m
我们可以看到3个pods已经启动。
https://github.com/FengZeHe/LearnGolang/tree/main/project/BasicProject