主要介绍docker、docker-compose、dockerfile编写以及项目部署k8s。 部署项目:
- traefik
- react 前端
- golang 微服务后端
- consul
- kafka
- kafka-manager
- zookeeper
- redis
- gogs
所有配置文件均可在github上下载
Docker
为什么使用docker
- 环境统一
- 每个人node版本不一样,导致前端项目依赖构建的时候可能出错
- Golang 版本不一样,特性API可能变化导致非后端人员出错不好排查
- 环境隔离,容器之间只能端口访问互相不影响
- 比虚拟机开销低
本地搭建及K8S部署
docker 设置
先从官网下载docker安装,windows用户必须是旗舰版以上,家庭版不能用。
安装后启动,小图标右键 - 设置,要修改的内容如下 Resources
- ADVANCED
- 底下的Disk image location 修改路径,不然镜像打包时占用几十G,C盘可能不够用
- 配置够的话可以增加cpu和内存占用
- FILE SHARING
- 勾选一个盘,docker容器与宿主机文件共享时才能使用 Docker Engine
- registry-mirrors
- 镜像下载,推荐使用阿里源,在阿里云控制台里,google 一下如何找到。
- 其他的两个源也可以用。
"https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn", "https://xxx.mirror.aliyuncs.com"
文件如上,放在根目录或者项目某个文件夹内。 逐行解释,有些命令相同的不重复解释1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## file编写
部署docker后项目肯定要编写dockerfile,构建为镜像文件
### React前端
```dockerfile
FROM node:latest as builder
WORKDIR /usr/src/app
USER root
COPY . /usr/src/app
RUN npm config set registry https://registry.npm.taobao.org \
&& npm i \
&& npm run build
FROM nginx
WORKDIR /usr/share/nginx/html/
USER root
COPY --from=builder /usr/src/app/docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- FROM node:latest as builder
- 前端项目,构建时的环境为node,所以基础镜像为node
- as builder,起一个名字,后面会用到
- WORKDIR /usr/src/app
- 在docker环境内的工作目录
- USER root
- 登录权限为root用户
- COPY . /usr/src/app
- COPY 命令,第一个参数为宿主机的项目目录,第二个参数为复制到哪个目录下
- 同样的还有ADD命令,不过官方推荐COPY,可以搜下不同
- RUN xxx
- 运行命令行
- 这里先设置npm源,然后安装依赖,打包
- 换行的话最后加
\
,下一行加&&,不换行直接加&&
即可 - 如果构建错误,可以在这里用 ls 等命令查看输出日志
- FROM nginx
- 多阶段构建,一个优化手段,可以搜一下
- 上面的node镜像中依赖包很大,打包出来可能有1G+,但实际要用的只有dist目录
- 这里前端项目容器需要单独能运行,所以需要nginx指向目录并开启端口,使其他服务能访问到
- COPY –from=builder
- 第一行的as builder用处就来了,表示从镜像的某个目录下复制文件到此构建镜像的目录中
- 这里的两行COPY表示将nginx设置和前端项目构建的dist复制到本镜像中
- EXPOSE 80
- 镜像暴露端口,nginx用到
- CMD [“nginx”, “-g”, “daemon off;”]
- 容器启动后要运行的命令
- 同样可以使用 ENTRYPOINT 可以搜下区别
构建命令及说明docker build --network host -t account ./ -f ./deploy/docker/account.dockerfile
- –network host 表示使用宿主机的网络环境,可能用到代理什么的。
- -t account ./ 打包出的镜像名称,以及构建时目录的上下文,这里的上下文指COPY的第一个参数运行上下文。
- -f ./deploy/docker/account.dockerfile dockerfile配置文件存放目录。
- 建议使用上面的命令行在项目根目录构建,参数顺序不能乱调,重要的是,运行上下文的问题。
- 如果上下文在某个文件夹里,则docker image构建时,docker是访问不到文件夹外的文件的。
- 比如如果运行命令在src目录里,则docker是的COPY . 上下文是在src下,package.json是无法访问的,就算使用RUN cd ..改变目录也不行。
- 因为使用了多阶段构建,打包完后会有两个镜像,一个是account,一个是
<none>
。 - account是我们要的,
<none>
是构建第一阶段node环境出来的镜像。
Golang后端
我自己的项目为Golang 微服务化的后端,所以这里的例子也以此构建
1 | FROM golang:1.13.5 as builder |
逐行解释,部分命令跟前端重合,不重复讲
- ENV
- 环境变量,go需要用到的
- RUN
- mkdir dist 创建文件夹,将编译的程序放进去
- CGO_ENABLED=0 go build -a -installsuffix cgo 关闭cgo,不然有报错,具体可以搜一下
- FROM alpine:latest
- alpine镜像,一个小巧的linux系统
- 里面没有bash,所以进入运行中的容器命令要用sh
docker exec -it xx sh
- RUN chmod -R 777 /usr/bin/server
- 设置目录权限
- #CMD exec /bin/sh -c “trap : TERM INT; (while true; do sleep 1000; done) & wait”
- 这段注释了,有时候会用到
- 镜像构建成功但镜像运行失败的话,这句某些情况可以阻止运行挂掉,可以进到运行的容器内运行命令
常用命令
- 列出所有镜像
docker image list
- 删除无用的镜像
docker rmi $(docker images -f dangling=true -q)
- 进入容器
docker exec -it xx bash
- 查看实例
docker ps -a
- 停止
docker stop xx
- 删除
docker rm xx
- 运行
docker run -d --net=backend -p 宿主机端口:容器端口 -v 宿主机目录:容器目录 account
docker-compose
容器编排,不需要 docker run
然后加一堆参数
本地运行时可以使用这个,比K8S方便,就是如果服务器有k8s则要写两套配置
docker-compose.yml
1 | version: "3" |
- 跟docker启动参数差不多
- depends_on
- 前置运行的容器,等这个容器运行后再运行当前容器
常用命令
- docker-compose down 删除所有容器
- docker-compose stop 停止一个已运行的容器,但不删除他
- docker-compose start 启动被停止的容器
- docker-compose build 构建或重新构建服务
- docker-compose up -d 会在后台启动容器并使它们运行
- docker restart 76e79889f101 重启某个容器
- docker-compose restart 重启所有容器
关于搭建mysql,gogs服务,可以看下我的一篇文章
Kubernetes
搭建
大陆用户因为众所周知的原因,这里k8s很难启动,所以需要特殊的方式。
注意: 全程不要挂代理!全程不要挂代理!全程不要挂代理!否则k8s访问本地服务会出问题!
中途有错误可以在C:\ProgramData\DockerDesktop/service.txt
里找到报错,如果出现访问网址404的错误,把代理关掉。
按照链接让k8s启动,能启动就可以了
https://github.com/AliyunContainerService/k8s-for-docker-desktop
部署dashboard
命令行可能出现403验证的问题,可以将文件下载下来执行。
recommended 版本会变化,项目地址如下,在releases里查找对应docker的版本
kubectl create -f .\recommendedv.yaml
部署token,这个是创建admin-user
dashboard-adminuser.yaml
1 | apiVersion: v1 |
kubectl create -f .\dashboard-adminuser.yaml
查看 Token 找到 admin-user-tokenkubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
开启服务kubectl proxy
dashboard有v2版本,查看地址有两种
v1http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
v2http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
查看服务,可能用到kubectl get pods,svc --all-namespaces -o wide
至此k8s应该可以访问了。
云上推荐使用提供的 容器服务,可以做到ci/cd那套玩法,镜像中心构建自己的镜像,配置好触发器即可。
部署服务
traefik
介绍及说明
一个均衡负载器,支持动态路由以及中间件,配合微服务非常好用。
这里有个问题,在本地可以使用 LoadBalancer 方式部署,将POD的80\443端口暴露给宿主机,然后所有流量通过traefik进行转发。但是在腾讯云上,NodePort暴露的端口只能在30000-32767之间,无法直接暴露80/443端口。而 LoadBalancer 由云厂商接管,使用这个需要付费。为了规避这个问题,要在宿主机上直接搭建一个 nginx,将所有的80/443端口流量转发到 traefik 的端口上。
本地和云上搭建配置文件有些不一样。
配置在github/traefik && github/traefik-tencent 里
配置文件讲解
crd,rbac
不多介绍,就是新增权限和 IngressRoute 类型路由config
用默认的就行,具体可以看官网说明route.yaml
中Host
部分网址,改成你想要的,比如traefik.k8s.com
- 配置文件包含了一份 consul 的配置,不需要可以删掉
- IngressRoute: 路由配置,每次新增路由使用该配置进行新增/修改路由
- IngressRoute: entryPoints 参数, web 表示80端口,websecure 表示用了SSL的443端口
- Secret: 存储在k8s内的秘钥
- Middleware: 中间件,路由时会经过此配置,对应IngressRoute中middlewares配置
本地搭建
- 对
config,crd,deploy,rbac,route
执行命令kubectl apply -f ./xxx.yaml
即可 - 有的教程写要带上
-n kube-system
部署到 kube-system 命名空间里,但是在腾讯云中部署时会出错,实测不带也可以 - dashboard 里可以看到服务启动了,然后直接输入
localhost:8080
可以访问 traefik dashboard - 设置hosts
127.0.0.1 traefik.k8s.com
,即可使用地址访问traefik dashboard,不再需要额外放开8080端口
云上搭建
云上有些不一样
- 云上POD暴露端口由server控制,原理是云上的POD内部有端口映射工具。
- 云上建议对域名访问加traefik的基础认证。
- 不要使用腾讯云提供的面板搭建traefik,用文件里的,否则报错。搭建完后记得配置Service。
先创建认证,再进行部署
route.yaml
的Secret
部分有个用户名密码字串,为访问域名时的基础。- 搜一下
在线生成 htpasswd
,用格式user:pwd
生成md5加密字符串 - 因为k8s存储的secret只能存储base64编码字符串或ssl,所以转出来的字符再用base64编码
- 将字串放到 Secret 的
users
下面 - 云上部署用
\traefik-tencent
文件替换掉\traefik
内的文件,再执行kubectl apply -f ./xxx.yaml
云上的traefik搭建就完成了,接下来需要宿主机的nginx转发端口
Nginx 搭建
PCRE pcre-devel 安装 PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。
yum install -y pcre pcre-devel
zlib 安装 zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。
yum install -y zlib zlib-devel
OpenSSL 安装 OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。
nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。yum install -y openssl openssl-devel
在官网下载安装包
https://nginx.org/en/download.html
wget -c https://nginx.org/download/nginx-1.16.1.tar.gz
tar zxvf nginx-1.16.1.tar.gz
cd nginx-1.16.1
./configure --with-http_gzip_static_module --with-http_ssl_module --with-http_v2_module
make && make install
启动/usr/local/nginx/sbin/nginx
设置开机自启vim /etc/rc.local
最下面加入一行 /usr/local/nginx/sbin/nginx
就可以了
配置转发到 traefik ,直接贴出配置文件供参考。
我这里用了ssl,不需要的可以自行修改。域名的SSL在nginx上设置,traefik 配置无效。http://127.0.0.1:30443
端口为 traefik 的端口
1 | server { |
这样就搭建好了,可以访问网站试下能不能进入到 traefik dashboard 里
consul & zookeeper
单机版本,配置查看github项目即可
consul 云上无需部署 services.yaml
gogs
需要修改镜像地址,腾讯云的docker hub 找不到 gogs 镜像,所以自己编译,并镜像公开了,如果不是腾讯云部署可以改为docker hub地址
app.ini 存放到 /data/gogs/gogs/conf/
内
具体配置查看 gogs 文档
redis
redis.conf 修改 requirepass
值为访问密码
配置的主要点在于映射 /etc/redis
目录,目录下有 redis.conf
,所以将 redis.conf 存放到 /data/redis/conf/
内
运行命令 redis-server
, 运行参数 /etc/redis/redis.conf
redis.conf 官网下载的,去掉了注释,实际上要用的就前两行,其他的都是默认值
1 | requirepass xxx |
kafka
因为走内网,可以不提供公网服务,于是也没加验证。
deployment 中有几个值讲一下:
- KAFKA_ADVERTISED_HOST_NAME: kafka 服务ip的值,由于不能填写127.0.0.1或localhost所以等创建好server后再修改配置
- KAFKA_ZOOKEEPER_CONNECT: zookeeper 的ip,所以要等zookeeper搭建后再创建kafka
- KAFKA_ADVERTISED_LISTENERS: 外网服务ip,不需要外网服务可以不写
测试一下
1
2
3kubectl exec -it kafka-6b6c6d4d4d-tv2qq /bin/bash
kafka-console-producer.sh --broker-list 172.16.255.xx:9092 --topic oss
kafka-console-consumer.sh --bootstrap-server 172.16.255.xx:9092 --topic oss
kafka-manager
修改 deployment 中 ZK_HOSTS
值为 zookeeper 的ip地址
面板上新建clusters时,连接为zk地址,zk-ip:port
K8S 常用命令
资源类型: secret, pod 等等
- 创建某个资源
kubectl apply -f ./xxx.yaml
- 获取某个资源
kubectl get xxx
- 删除某个资源
kubectl detele 资源类型 xxx
- 按文件删除某个资源
kubectl detele -f ./xxx.yaml