- Введение
- построить в докере
- Интегрирован в docker-compose
- Использовать обратный прокси nginx
- Суммировать
- Текущий раздел кода
Введение
В конце концов, тесты и документация готовы, осталось только развертывание.
Может использоваться непосредственно во время обычного тестированияgo run
работает, но когда дело доходит до развертывания для скомпилированных языков,
определенно хочу использоватьgo build
Генерировать бинарные файлы.
построить в докере
Поскольку вся система основана на docker-compose, вам нужно написать Dockerfile, Соберите весь проект в виде образа в докере.
Таким образом, его можно запустить прямо в докере.Процесс генерации бинарных файлов для каждой локальной сборки, Это превращается в пересборку образа докера.
Dockerfile выглядит следующим образом:
FROM golang:1.13 as build
ENV GOPROXY="https://goproxy.io"
# https://stackoverflow.com/questions/36279253/go-compiled-binary-wont-run-in-an-alpine-docker-container-on-ubuntu-host
# build for static link
ENV CGO_ENABLED=0
WORKDIR /app
COPY . /app
RUN make build
# production stage
FROM alpine as production
WORKDIR /app
COPY ./conf/ /app/conf
COPY --from=build /app/web /app
EXPOSE 8081
ENTRYPOINT ["/app/web"]
CMD [ "-c", "./conf/config_docker.yaml" ]
При построении используется двухэтапная сборка: сначала бинарный файл собирается в обычном образе golang. Затем скопируйте его в образ alpine, чтобы уменьшить размер образа после завершения сборки.
Переменные среды должны быть установлены при построенииCGO_ENABLED=0
, чтобы отключить использование динамической компоновки CGO,
Пожалуйста, обратитесь кstackoverflow.
Интегрирован в docker-compose
Когда Dockerfile написан, вы можете напрямую собрать образ и запустить тест, чтобы увидеть, работает ли он.
docker build -t go_web .
docker run -p 8081:8081 go_web
Когда все хорошо, его можно интегрировать вdocker-compose.yaml
, названный службой.
app:
build:
context: .
depends_on:
- mysql
Есть зависимость, ведь mysql должен быть запущен первым.Что касается того, почему порт не выставлен, это потому, что используется обратный прокси nginx.
Использовать обратный прокси nginx
docker-compose может вручную масштабировать СЛУЖБУ до нескольких экземпляров.
Usage: up [options] [--scale SERVICE=NUM...] [SERVICE...]
Хотя масштабирование docker-compose больше не популярно после выхода kubernetes, давайте его реализуем. Здесь мы фокусируемся только на расширении приложения, то есть текущего проекта, независимо от других зависимостей, таких как базы данных.
Изменить API
Сначала внесите изменения/check/health
API возвращает имя хоста, чтобы можно было наблюдать эффект.
var hostname string
func init() {
name, err := os.Hostname()
if err != nil {
name = "unknow"
}
hostname = name
}
// HealthCheck 返回心跳响应
func HealthCheck(ctx *gin.Context) {
message := fmt.Sprintf("OK from %s", hostname)
ctx.String(http.StatusOK, message)
}
После завершения модификации обратите внимание на перестроение образа, чтобы модификация вступила в силу.
создать службу nginx
Настройте nginx в docker-compose.
nginx:
image: nginx:stable-alpine
ports:
- 80:80
depends_on:
- app
volumes:
- ./conf/nginx_web.conf:/etc/nginx/conf.d/default.conf
command: nginx -g 'daemon off;'
Затем напишите файл конфигурации nginx:
upstream web {
server app:8081;
}
server {
listen 80;
server_name localhost;
location / {
# https://stackoverflow.com/questions/42720618/docker-nginx-stopped-emerg-11-host-not-found-in-upstream
resolver 127.0.0.1;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 5m;
proxy_pass http://web;
}
}
Здесь настроен обратный прокси для перенаправления всех запросовapp:8081
, это порт, предоставляемый сервером приложений,
Обратите внимание, что наборresolver 127.0.0.1;
, иначе nginx не сможет подключиться в началеapp:8081
разбился сразу.
Так почему бы не запустить NGINX, когда будете готовы?depends_on
Гарантируется только то, что порядок запуска гарантирован, а не подтверждается, что он готов.
обновление базы данных
То же самое верно и для базы данных, нам нужно установить определенный механизм повторных попыток, чтобы убедиться, что база данных была запущена.
func openDB(username, password, addr, name string) *gorm.DB {
config := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s&timeout=10s",
username,
password,
addr,
name,
true,
// "Asia%2FShanghai", // 必须是 url.QueryEscape 的
"Local",
)
var db *gorm.DB
var err error
for i := 0; i < 10; i++ {
db, err = gorm.Open("mysql", config)
if err == nil {
break
}
time.Sleep(time.Second * 3)
}
if db == nil {
logrus.Fatalf("数据库连接失败. 数据库名字: %s. 错误信息: %s", name, err)
}
logrus.Infof("数据库连接成功, 数据库名字: %s", name)
setupDB(db)
return db
}
Кроме того, при запуске базы данных задайте сценарий инициализации, чтобы вам не приходилось вручную создавать базу данных.
mysql:
image: mysql:8
command: --default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql
environment:
MYSQL_ROOT_PASSWORD: "1234"
ports:
- 3306:3306
volumes:
- ./script/db.sql:/data/application/init.sql
Сценарий инициализации базы данных очень прост, достаточно проверить, существует ли определенная база данных, и создать ее, если она не существует.
CREATE DATABASE IF NOT EXISTS `db_apiserver`;
запускать
Когда все изменения сделаны, пора начинать и пробовать.
docker-compose up --scale app=3 nginx
Это запускает три экземпляра приложения.
если вы продолжите посещатьhttp://127.0.0.1:80/v1/check/health
, должно получиться три результата,
Аналогично следующему:
OK from 5f8a835b6797
OK from b6dbb50cecd5
OK from 87e98121950d
Первые несколько посещений могут возвращать ошибку 502, поскольку приложение все еще подключается к базе данных и не запущено.
Затем вы можете изменить конфигурацию nginx, чтобы использовать различные механизмы балансировки нагрузки, встроенные в nginx.
Рекомендуется использовать предыдущий使用 Go 添加 Nginx 代理
использовать вместе.
Суммировать
Есть много способов развертывания GO, просто выберите правильный. Если вам это нужно, вы также можете пересекать двоичные файлы для каждой платформы.
Текущий раздел кода
как версияv0.17.0