【GoTeams】-5:引入Docker

本文目录

1. Dokcer-compose

这里简单先用一下win版本的Docker,后期开发好了部署的时候再移植到服务器下进行docker部署。

输入命令docker-compose version 就可以看到已经装好的docker版本了,顺便装一个dockerdesktop。

回顾下Docker知识

Docker 是一个开源的应用容器引擎 ,它通过容器技术来实现轻量级的虚拟化。容器允许开发者将应用及其所有依赖包打包到一个可移植的容器中,以便在任何环境中一致地运行。

Docker Compose 是 Docker 官方提供的一个工具,用于定义和运行多容器的 Docker 应用。通过 Compose,用户可以使用 YAML 文件来定义多个 Docker 容器的服务、网络、存储卷等配置,并通过一个命令(docker-compose up)启动所有定义好的服务。

Dockerfile 是用来构建 Docker 镜像的文件,包含创建镜像的步骤和指令,可以与 Docker Compose 配合使用,在 Compose 中定义服务时使用自定义的 Docker 镜像。

编写docker-compose.yaml

目前需要部署Mysql、Redis、Etcd、User、Api服务,所以需要编写一下Docker方便以后启动。

创建一个docker-compose.yaml文件,然后进行容器编排。

go 复制代码
version: '3'
services:
  mysql:
    container_name: mysql8
    image: mysql:${MYSQL_VERSION}
    restart: always
    ports:
      - 3309:3306
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: msproject
    volumes:
      - ${MYSQL_DIR}/data:/var/lib/mysql
      - ${MYSQL_DIR}/conf:/etc/mysql/conf.d/
      - ${MYSQL_DIR}/logs:/logs
    command:
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1

这里大致讲一下进行了什么操作,回顾下之前学过的docker容器。

首先定义容器名称,container_name: mysql8,定义了容器的名称为 mysql8,可以通过这个名称来管理MySQL容器。

image: mysql:${MYSQL_VERSION}该配置使用指定版本的MySQL镜像,${MYSQL_VERSION} 是一个变量,表示MySQL的版本号。该变量的实际值在运行时会由环境变量提供。

3309:3306 将容器的3306端口(MySQL默认端口)映射到主机的3309端口。可以通过主机的3309端口访问容器中的MySQL服务。

MYSQL_DATABASE: msproject 创建一个名为msproject的数据库。

${MYSQL_DIR}/data:/var/lib/mysql 将主机上 ${MYSQL_DIR}/data 目录映射到容器的 /var/lib/mysql 目录,这是MySQL存储数据的位置。

${MYSQL_DIR}/conf:/etc/mysql/conf.d/ 将主机上 ${MYSQL_DIR}/conf 目录映射到容器的 /etc/mysql/conf.d/,用于配置MySQL。

${MYSQL_DIR}/logs:/logs 将主机上 ${MYSQL_DIR}/logs 目录映射到容器的 /logs 目录,用于存储MySQL的日志。

然后是Redis的持久化。

go 复制代码
  Redis:
    container_name: redis6
    image: redis:${REDIS_VERSION}
    restart: always
    volumes:
      - ${REDIS_DIR}/data:/data
      - ${REDIS_DIR}/conf/redis.conf:/etc/redis/redis.conf
    ports:
      - ${REDIS_PORT}:6379
    command: redis-server /etc/redis/redis.conf

Etcd持久化。

go 复制代码
  Project-User:
    container_name: project-user
    image: project-user:latest
    ports:
      - 8080:8080
      - 8881:8881

User服务持久化。

go 复制代码
  Etcd:
    container_name: etcd3
    image: bitnami/etcd:${ETCD_VERSION}
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
    environment:
      - ALLOW_NONE_AUTHENTICATION=yes
    privileged: true
    volumes:
      - ${ETCD_DIR}/data:/bitnami/etcd/data
    ports:
      - ${ETCD_PORT}:2379
      - 2380:2380

上面我们有一些需要环境提供的参数,这里需要在.env环境编写。

go 复制代码
MYSQL_VERSION=8.0.20
MYSQL_DIR=D:\GoProject\msproject-data\mysql
MYSQL_PORT=3309
REDIS_VERSION=6.2.7
REDIS_PORT=6379
REDIS_DIR=D:\GoProject\msproject-data\redis
ETCD_VERSION=3.5.6
ETCD_PORT=2379
ETCD_DIR=D:\GoProject\msproject-data\etcd

此外还需要在redis下来配置.conf文件D:\GoProject\msproject-data\redis\conf

go 复制代码
# 任意ip可访问
bind 0.0.0.0
# 自定义启动端口
port 6379
# rdb或aof文件存储位置
dir /data
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename "appendonly.aof"

运行docker

我们在项目路径下直接docker-compose up -d,-d的作用是后台启动,然后直接等待拉取启动即可。

在desktop中能看到帮我们拉取的镜像。

以及启动的容器。

通过redis试试是否能够添加成功。

go 复制代码
CREATE TABLE `ms_member`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '系统前台用户表',
  `account` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户登陆账号',
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '登陆密码',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户昵称',
  `mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机',
  `realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '真实姓名',
  `create_time` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建时间',
  `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态',
  `last_login_time` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上次登录时间',
  `sex` tinyint(0) NULL DEFAULT 0 COMMENT '性别',
  `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '头像',
  `idcard` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证',
  `province` int(0) NULL DEFAULT 0 COMMENT '省',
  `city` int(0) NULL DEFAULT 0 COMMENT '市',
  `area` int(0) NULL DEFAULT 0 COMMENT '区',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所在地址',
  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '备注',
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  `dingtalk_openid` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '钉钉openid',
  `dingtalk_unionid` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '钉钉unionid',
  `dingtalk_userid` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '钉钉用户id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1000 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = COMPACT;

我们把准备好的表,在mysql中导入。

这样服务就跑起来了,我们来看看现在etcd是否能用。

分别把user服务和api服务跑起来,然后看看前端是否能够正常请求。

验证无误,现在把mysql、redis、etcd迁移到docker上了,查询redis也能够查询到记录的验证码!

2. 部署go服务

需要把go服务也编译打包成镜像,然后运行起来。下面是一个编译的脚本。

go 复制代码
chcp 65001
@echo off
:loop
@echo off&color 0A
cls
echo,
echo 请选择要编译的系统环境:
echo,
echo 1. Windows_amd64
echo 2. linux_amd64

set/p action=请选择:
if %action% == 1 goto build_Windows_amd64
if %action% == 2 goto build_linux_amd64

:build_Windows_amd64
echo 编译Windows版本64位
SET CGO_ENABLED=0
SET GOOS=windows
SET GOARCH=amd64
go build -o project-user/target/project-user.exe project-user/main.go
go build -o project-api/target/project-api.exe project-api/main.go
:build_linux_amd64
echo 编译Linux版本64位
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o project-user/target/project-user project-user/main.go
go build -o project-api/target/project-api project-api/main.go

在脚本下执行build 命令,然后进行编译,这里我们需要编译linux版本,放到docker中去。

编写dockerfile

写dockerfile是为了编译成镜像。

go 复制代码
FROM alpine
WORKDIR /Initial
COPY ./target/project-user .
COPY ./config/config-docker.yaml .
RUN  mkdir config && mv config-docker.yaml config/config.yaml
EXPOSE 8080 8881
ENTRYPOINT ["./project-user"]

FROM alpine指定了构建镜像所使用的基础镜像为 alpine,这是一个非常轻量的 Linux 发行版。使用 alpine 作为基础镜像,可以减小镜像的体积,因为 alpine 镜像通常非常小,只有几十兆。

WORKDIR /Initial 设置容器内的工作目录为 /Initial。工作目录是指在容器中运行命令时默认的目录。如果该目录不存在,WORKDIR 会创建它。

COPY ./target/project-user .将本地系统中的 ./target/project-user 文件复制到 Docker 容器中的当前工作目录(即 /Initial)中。

COPY ./config/config-docker.yaml . 将本地系统中的 ./config/config-docker.yaml 文件复制到 Docker 容器的当前工作目录(/Initial)中。此文件通常用于存储容器中应用的配置文件。

RUN mkdir config && mv config-docker.yaml config/config.yaml ,首先在在容器的当前工作目录中创建一个名为 config 的新目录。然后mv config-docker.yaml config/config.yaml:将之前复制到容器中的 config-docker.yaml 文件重命名为 config/config.yaml 并移动到新创建的 config 目录中。

EXPOSE 8080 8881 告知 Docker 容器将暴露端口 8080 和 8881,意味着容器运行时,这些端口将会被开放,并允许主机或其他容器与之通信。需要注意的是,EXPOSE 仅是一个声明,它不会自动将端口映射到主机上,实际的端口映射需要通过 docker run -p 或 docker-compose.yml 配置来完成。

ENTRYPOINT ["./project-user"] 指定容器启动时的默认命令。ENTRYPOINT 设置容器运行时的入口点,容器启动后,会执行 ./project-user 这个命令。通常,ENTRYPOINT 用来指定容器的主进程。在这里,./project-user 是容器内的一个可执行文件,它会在容器启动时运行。

然后我们需要把原来config文件复制一份改为config-docker.yaml文件,并且需要修改配置代码。原本我们的server地址是127.0.0.1,这是本地回环地址,任何绑定在 127.0.0.1 上的服务只能在本地机器上访问,不能从其他机器或者网络中访问

需要改为0.0.0.0,绑定到 0.0.0.0 上的服务将接受来自所有网络接口(包括外部网络接口)的请求。这意味着服务不仅能接受本地机器的请求,还能接受来自其他机器或容器的请求。

go 复制代码
server:
  name: "project-user"
  addr: "0.0.0.0:8080"
zap:
  debugFileName: "/logs/debug/project-debug.log"
  infoFileName: "/logs/info/project-info.log"
  warnFileName: "/logs/error/project-error.log"
  maxSize: 500,
  maxAge: 28,
  MaxBackups: 3
redis:
  host: "redis6"
  port: 6379
  password: ""
  db: 0
grpc:
  addr: "0.0.0.0:8881"
  name: "user"
  version: "1.0.0"
  weight: 2
etcd:
  addrs:
    - "etcd3:2379"

也就是说,在 Docker 容器中,通常容器中的服务是通过 容器的网络接口 与其他容器或主机进行通信的。如果你将应用绑定到 127.0.0.1,那么它将只能接受来自容器内部(即容器的网络栈)或者本地机器的请求,而不能接受外部请求。这对多容器应用或需要外部访问的服务(如 Web 服务、gRPC 服务等)会构成问题。

同时还要对redis和etcd的容器名设定好,已经起来的容器名称是redis6和etcd3,我们需要对应设置好。

并且在docker-compoose.yaml的文件下,加入User相关配置。

go 复制代码
  Project-User:
    container_name: project-user
    image: project-user:latest
    ports:
      - 8080:8080
      - 8881:8881

然后再写一个run.bat的脚本,一起来打包运行。

go 复制代码
chcp 65001
cd project-user
docker build -t project-user:latest .
cd ..
docker-compose up -d

chcp 65001 用于 设置命令行的字符编码 为 UTF-8(65001 是 UTF-8 编码的代码页)。

docker build -t project-user:latest .构建 Docker 镜像的命令。-t project-user:latest:这是为构建出来的 Docker 镜像指定一个标签(-t 参数),标签为 project-user:latest。latest 是镜像的版本标签,意味着这是最新版本的镜像。.:指的是当前目录(即 project-user 目录)。构建过程会查找当前目录下的 Dockerfile 文件,使用 Dockerfile 中的指令来构建镜像。

docker-compose up -d 也就是cd到上层目录之后,会根据当前目录下的 docker-compose.yml 文件来启动定义的服务。docker-compose.yml 文件通常包含一个或多个服务(如 Web 服务、数据库服务等)的配置。

然后我们来run这个bat脚本,然后等待运行即可。(这个过程需要魔法,不然会失败,这个点大家自行解决即可。)

嗯,魔法也不行,魔法只能pull,但是不能构建dockerfile,会一直提示报错,这里还需要添加docker的镜像地址。

go 复制代码
{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "registry-mirrors": [
        "https://docker.registry.cyou/",
        "https://docker-cf.registry.cyou/",
        "https://dockercf.jsdelivr.fyi/",
        "https://docker.jsdelivr.fyi/",
        "https://dockertest.jsdelivr.fyi/",
        "https://mirror.aliyuncs.com/",
        "https://dockerproxy.com/",
        "https://mirror.baidubce.com/",
        "https://docker.m.daocloud.io/",
        "https://docker.nju.edu.cn/",
        "https://docker.mirrors.sjtug.sjtu.edu.cn/",
        "https://docker.mirrors.ustc.edu.cn/",
        "https://mirror.iscas.ac.cn/",
        "https://docker.rainbond.cc/",
        "https://jq794zz5.mirror.aliyuncs.com"
    ]

}

这里我们在docker引擎里面设置即可。

现在再重新run.bat这个脚本,就可以构造我们user的镜像,并且运行全部的docker compose了。


这个时候我们也能看到user镜像了。

现在启动就可以不用通过本地goland用go run 命令启动服务了,已经在容器里面跑起来了。

通过命令docker logs -f project-user可以查看对应的docker容器日志。

然后在本地启动api服务,在前端发送请求,验证成功。

此时user容器的日志也已更新。

如果后续改动了代码,需要验证的话,步骤就是先运行命令build.bat命令,build对应的linux版本。也就是先编译Go程序为linux版本。

然后运行run.bat脚本,重新编译镜像并运行容器。这样等待重新生效即可。


后续如何在linux下查看占用的端口情况,这里有两个命令:

go 复制代码
netstat -tulnp

ss -tuln
相关推荐
howard20055 小时前
Docker实战 - 将Web项目打成war包部署到tomcat容器里运行
docker·容器化部署web项目
p***c9495 小时前
Docker机器学习实战
机器学习·docker·容器
pumpkin845147 小时前
Docker 参考手册
chrome·docker·容器
三天不学习9 小时前
GitLab Docker 安装完整配置项说明
docker·容器·gitlab
北冥有鱼被烹12 小时前
【微知】Ubuntu中如何安装docker?
ubuntu·docker
幻灭行度15 小时前
docker镜像导入到K8S的containerd中
java·docker·kubernetes
虎头金猫15 小时前
随时随地处理图片文档!Reubah 加cpolar的实用体验
linux·运维·人工智能·python·docker·开源·visual studio
哈里谢顿1 天前
Docker 中快速启动 Prometheus + Grafana操作指南(二)
docker
醇氧1 天前
Mac 安装 Docker Desktop
macos·docker·容器
哈里谢顿1 天前
Docker 中快速启动 Prometheus + Grafana操作指南
docker