docker部署

2023-06-15 20:09:52

技术

基本使用

编写 Dockerfile

在项目根目录下编写Dockerfile(默认使用名称就是Dockerfile,不需要后缀)

FROM golang:alpine

# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# 移动到工作目录:/build
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 将我们的代码编译成二进制可执行文件app
RUN go build -o app .

# 移动到用于存放生成的二进制文件的 /dist 目录
WORKDIR /dist

# 将二进制文件从 /build 目录复制到这里
RUN cp /build/app .

# 声明服务端口
EXPOSE 9000

# 启动容器时运行的命令
CMD ["/dist/app"]

构建 docker 镜像

项目根目录下执行,创建镜像并制定镜像名为 web_app

docker build . -t web_app

运行镜像

指定端口运行镜像

docker run -p 9000:9000 web_app

最佳实践

分阶段构建

Go 程序编译之后会得到一个可执行的二进制文件,在最终的镜像中是不需要 go 编译器的,但是以上的 dockerfile 会把 go 的编译环境也打包到镜像中。

分阶段构建的目的是仅打包需要打包的,尽可能地减小镜像的体积

###################
# 1. AS: 构建阶段作为一个镜像,命名为 builder
###################
FROM golang:alpine AS builder

# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# 移动到工作目录:/build
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 将我们的代码编译成二进制可执行文件 app
RUN go build -o app .

###################
# 2. 创建一个小镜像,scratch 是 docker 中的最小镜像
###################
FROM scratch

# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/app /

# 需要运行的命令
ENTRYPOINT ["/app"]

将编译环境的部分给忽略掉,只把可执行文件的镜像拷贝到一个最小镜像中

拷贝其他文件

除了go还附带其他文件,比如网页的静态文件等等则需要拷贝,一起放在镜像中

...
FROM scratch

COPY ./templates /templates
COPY ./static /static
COPY ./conf /conf
...

不过这种是前后端放在一起部署,并非所谓的前后端分离,前后端分离一般会是使用 nginx 来部署,之后再介绍。

多容器

容器关联

在使用多个容器时会用到,比如在使用 MySQL 时是用的docker容器,容器名为MySQL123。那么在配置文件中修改host项为容器名,如:

host: mysql123

修改后重新构建镜像

docker build . -t web_app

运行应用容器并与容器mysql123关联

docker run --link=mysql123:mysql123 -p 8888:8888 web_app_app

docker compose(容器编排)

参考于别处

  1. 使用Dockerfile定义你的应用环境以便可以在任何地方复制。
  2. 定义组成应用程序的服务,docker-compose.yml 以便它们可以在隔离的环境中一起运行。
  3. 执行 docker-compose up命令来启动并运行整个应用程序。

编写docker-compose.yml

文件名:docker-compose.yml
# yaml 配置
version: "3.7"
services:
  # mysql容器
  mysql8019:
    image: "mysql:8.0.19"
    ports:
      - "33061:3306"
    command: "--default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql"
    environment:
      MYSQL_ROOT_PASSWORD: "mysql123"
      MYSQL_DATABASE: "web_app"
      MYSQL_PASSWORD: "mysql123"
    volumes:
      - ./init.sql:/data/application/init.sql # 数据库初始化
    
  # redis容器, 参考mysql即可
  redis:
    image: ""
    ports:
      - ""

  # 应用程序的容器
  web_app:
    build: .
    command: sh -c "./wait-for.sh mysql8019:3306 redis:6379 -- ./web_app ./conf/config.ini"
    depends_on:
      - mysql8019
    ports:
      - "9000:9000"

容器的编排有先后顺序,以上述为例,必须先启动mysql与redis后才能启动应用程序。

编写Dockerfile

FROM golang:alpine AS builder

# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# 移动到工作目录:/build
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 下载依赖信息
RUN go mod download

# 将我们的代码编译成二进制可执行文件 web_app
RUN go build -o web_app .

###################
# 接下来创建一个小镜像
###################
FROM debian:stretch-slim

# 从builder镜像中把脚本拷贝到当前目录
COPY ./wait-for.sh /

# 从builder镜像中把静态文件拷贝到当前目录
COPY ./templates /templates
COPY ./static /static

# 从builder镜像中把配置文件拷贝到当前目录
COPY ./conf /conf


# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/web_app /

RUN set -eux; \
    apt-get update; \
    apt-get install -y \
        --no-install-recommends \
        netcat; \
        chmod 755 wait-for.sh

# 不在Dockerfile里运行
# ENTRYPOINT ["/web_app", "conf/config.ini"]

执行

docker-compose up