使用 Docker 和 Traefik v1 搭建輕量代碼倉庫(Gogs)

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或從新修改使用,但須要註明來源。 署名 4.0 國際 (CC BY 4.0)css

本文做者: 蘇洋html

建立時間: 2020年02月04日 統計字數: 12336字 閱讀時間: 25分鐘閱讀 本文連接: soulteary.com/2020/02/04/…mysql


使用 Docker 和 Traefik v1 搭建輕量代碼倉庫(Gogs)

本文成文於 2019年9月,將介紹如何使用 Traefik v1 搭建易於維護管理的 Gogs 。git

原計劃是替換家中 HomeLab 的代碼倉庫,但因爲 GitLab CI 的良好體驗,家裏的 HomeLab 最終仍是選擇繼續使用 GitLab。redis

這篇文章也就沉入了草稿箱,最近在折騰 Traefik 升級和測試服務器,遇到了一些相關的小需求,故將內容更新了一些後發佈出來,但願能幫到有須要的同窗。sql

寫在前面

一直以來,都在使用 GitLab 做爲團隊/我的的倉庫工具,隨着版本的不斷升級,GitLab 的界面功能愈來愈強大,消耗的服務器資源也愈來愈多。docker

最近將 GitLab Community Edition 升級到了 12.3+ ,服務器上依舊是絲般順滑,可是家裏 UPS 顯示服務器待機功率默默上去了 10w。數據庫

這 10w 消耗的電費是小,可是本來靜音的服務器,開始了輕微的風扇轉動,這就有些不能忍了,因而有了使用更輕量應用替換 GitLab 的想法。編程

前置準備

Gogs 自身支持 HTTPS、支持掛在 SSL 證書,可是考慮到可維護性,這個事情交託給 Traefik 來處理。json

Gogs 默認數據庫使用的是 SQLite,輕量有餘,可是做爲重要數據的數據後端卻不是那麼安全,從官方網站的「如何修復數據庫」能夠看到掛掉的可能性仍是很多的,因此咱們要將其替換。

Gogs 默認的緩存方案是應用自己的內存,通常來講足夠應付我的/小團隊使用,可是爲了進一步提升性能和健壯性,咱們將緩存功能從應用主體解耦,交託於 Redis 進行處理。

那麼開始配置 Gogs 依賴的軟件和環境吧。

配置 MySQL 數據庫

使用 compose 配置數據庫很是簡單,二十行之內解決戰鬥:

version: '3.6'

services:

  db:
    image: mysql:5.7.16
    restart: always
    expose:
      - 3306
    volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
	  # - /etc/timezone:/etc/timezone:ro
      - ./mysql:/var/lib/mysql
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: gogs
      MYSQL_DATABASE: gogs
      MYSQL_USER: gogs
      MYSQL_PASSWORD: gogs
      TZ: Asia/Shanghai
複製代碼

配置 Redis 內存緩存

使用 compose 搞定 Redis 更爲簡單,由於咱們不須要將緩存持久化,因此不到二十行就完事了:

cache:
    image: redis:5.0-alpine
    restart: always
    expose:
      - 6379
    environment:
      TZ: Asia/Shanghai
    # volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
      # - /etc/timezone:/etc/timezone:ro
複製代碼

配置 Gogs 應用

不須要 Traefik 、MySQL、Redis 的 Gogs 編排文件顯得十分簡單:

version: '3.6'

services:

  app:
    image: gogs/gogs:0.11.91
    restart: always
    ports:
      - 22:22
      - 80:3000
    volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
      # - /etc/timezone:/etc/timezone:ro
      - ./data/:/data/
    labels:
      - "traefik.enable=true"
      - "traefik.port=3000"
      - "traefik.frontend.rule=Host:${GOGS_DOMIAN}"
      - "traefik.frontend.entryPoints=http,https"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.SSLProxyHeaders=X-Forwarded-Proto:https"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.frameDeny=true"

networks:
  traefik:
    external: true
複製代碼

可是這樣配置的應用,顯然少了「應用健康檢查」、「倉庫數據安全存儲」、「頁面高性能響應」的能力。

定製網絡環境

想讓 Gogs 、Redis、MySQL 做爲一個總體一塊兒正常工做,又不受到其餘應用干擾,須要作幾件事:

  • 將它們放置相同的網段
  • 僅對外暴露 Gogs ,對外隱藏 MySQL、Redis

想要達到這個效果,須要修改 docker-compose.yml 文件,定義 networks

version: '3.6'

services:

  app:
    networks:
      - traefik
      - gogs

  db:
    networks:
      - gogs


  cache:
    networks:
      - gogs

networks:
  gogs:
    internal: true
  traefik:
    external: true
複製代碼

上面的示例代碼中,咱們聲明瞭兩個網絡環境,分別爲私有網絡 gogs,用於 Gogs 和 MySQL、Redis 互通;外部的網絡 traefik,用於暴露 Web 服務、Git SSH 服務給用戶。

配置服務域名

應用網路互通後,Gogs 能夠經過 Docker 賦予的容器名稱訪問 MySQL、Redis,或者使用 gogs 隨機分配的內網地址進行數據交互。

然而這兩種方案都不是特別利於維護,一旦容器擴展/重建後,容器名稱會發生變化、分配的 IP 地址也會發生變化。

因此這裏可使用 compose 組網聲明 MySQL、Redis 的內網域名。

version: '3.6'

services:

  app:
    links:
      - db:mysql.gogs.lab.com
      - cache:cache.gogs.lab.com
複製代碼

而後在 Gogs 容器中訪問上面的域名就可以直接訪問到 MySQL、Redis 啦。

解決 Gogs 啓動時由於依賴服務未就緒報錯

若是你直接啓動包含三個應用的編排文件,可能會遇到 Gogs 報錯,因此能夠配合給三個應用都添加健康檢查,以及啓動依賴關係來解決問題:

version: '3.6'

services:

  app:
    depends_on:
      - db
      - cache
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:3000 || exit 1"]


  db:
    healthcheck:
      test: ["CMD-SHELL", "/etc/init.d/mysql status"]
      interval: 30s

  cache:
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
複製代碼

解決多網卡狀況下 Traefik 機率不工做的問題

如今,你可能會發現一向很靈敏的 Traefik 出現了偶爾不工做的問題,緣由是 Traefik 有時將端口暴露到了 gogs 私有網絡網卡上,解決方案很簡單,聲明 Traefik 工做使用的網卡就成:

version: '3.6'

services:

  app:
    labels:
      - "traefik.docker.network=traefik"
複製代碼

避免反代狀況下 Gogs 尋找服務域名

根據以前的經驗,反代的應用有可能會向公網 DNS 尋求幫助,查找服務域名,好比 gogs.lab.com ,爲了不這種狀況發生,應用出現轉半天轉不開的狀況,咱們能夠選擇讓 Gogs 容器的服務域名的解析地址映射爲本地:

version: '3.6'

services:

  app:
    extra_hosts:
      - "${GOGS_DOMIAN}:127.0.0.1"
複製代碼

持久化數據文件

相比較「默認方案」直接映射 /data 整個大目錄,若是將子目錄單獨映射,則能夠更好的控制應用數據遷移、配置更新。

version: '3.6'

services:

  app:
    volumes:
      - ./app.ini:/data/gogs/conf/app.ini:ro
      - ./logs:/data/gogs/data/log
      - ./data/avatars:/data/gogs/data/avatars
      - ./data/ssh:/data/ssh
      - ./data/git:/data/git
複製代碼

定製頁面模版

官方文檔中提到咱們能夠修改 custom/templates/inject/public/css 下的文件,來定製頁面展現。

可是容器中,這塊實際的目錄卻有一些變化,若是你有定製模版的需求,能夠參考下面的配置解決問題。

version: '3.6'

services:

  app:
    volumes:
     - ./data/custom/template/head.tmpl:/app/gogs/templates/inject/head.tmpl
      - ./data/custom/template/footer.tmpl:/app/gogs/templates/inject/footer.tmpl
      - ./data/custom/inject-assets/:/app/gogs/public/inject-assets/
複製代碼

限制 Gogs 的日誌文件大小

加上了健康檢查的 Gogs ,日誌會隨着時間慢慢變大,而這裏日誌對於咱們解決問題沒有絲毫幫助,因該被丟棄:

app_1    | [Macaron] 2019-09-28 07:07:04: Started GET / for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:07:04: Completed GET / 302 Found in 7.6542ms
app_1    | [Macaron] 2019-09-28 07:07:04: Started GET /user/login for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:07:04: Completed GET /user/login 200 OK in 16.5518ms
app_1    | [Macaron] 2019-09-28 07:07:34: Started GET / for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:07:34: Completed GET / 302 Found in 2.892ms
app_1    | [Macaron] 2019-09-28 07:07:34: Started GET /user/login for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:07:34: Completed GET /user/login 200 OK in 10.2743ms
複製代碼

配置 Gogs 應用日誌輸出選項,給出一個「最大尺寸」限制便可:

version: '3.6'

services:

  app:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
複製代碼

完整配置

將上述全部內容合併,完整的 docker-compose.yml 配置文件以下:

version: '3.6'

services:

  app:
    image: ${DOCKER_GOGS_IMAGE}
    restart: always
    networks:
      - traefik
      - gogs
    expose:
      - 3000
    ports:
      - 22:22
    links:
      - db:${MYSQL_HOST}
      - cache:${REDIS_HOST}
    depends_on:
      - db
      - cache
    labels:
      - "traefik.enable=true"
      - "traefik.port=3000"
      - "traefik.frontend.rule=Host:${GOGS_DOMIAN}"
      - "traefik.frontend.entryPoints=http,https"
      - "traefik.frontend.headers.SSLRedirect=true"
      - "traefik.frontend.headers.SSLProxyHeaders=X-Forwarded-Proto:https"
      - "traefik.frontend.headers.STSSeconds=315360000"
      - "traefik.frontend.headers.frameDeny=true"
      - "traefik.docker.network=traefik"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
    extra_hosts:
      - "${GOGS_DOMIAN}:127.0.0.1"
    volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
      # - /etc/timezone:/etc/timezone:ro
      - ./app.ini:/data/gogs/conf/app.ini:ro
      - ./logs:/data/gogs/data/log
      - ./data/avatars:/data/gogs/data/avatars
      - ./data/ssh:/data/ssh
      - ./data/git:/data/git
      # 根據本身需求使用
      # - ./data/custom/template/head.tmpl:/app/gogs/templates/inject/head.tmpl
      # - ./data/custom/template/footer.tmpl:/app/gogs/templates/inject/footer.tmpl
      # - ./data/custom/inject-assets/:/app/gogs/public/inject-assets/
    healthcheck:
      test: ["CMD-SHELL", "wget -q --spider --proxy off localhost:3000 || exit 1"]
      interval: 5s


  db:
    image: ${DOCKE_MYSQL_IMAGE}
    restart: always
    networks:
      - gogs
    expose:
      - 3306
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: gogs
      MYSQL_DATABASE: gogs
      MYSQL_USER: gogs
      MYSQL_PASSWORD: gogs
      TZ: Asia/Shanghai
    volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
      # - /etc/timezone:/etc/timezone:ro
      - ./mysql:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "/etc/init.d/mysql status"]
      interval: 30s


  cache:
    image: ${DOCKER_REDIS_IMAGE}
    restart: always
    networks:
      - gogs
    expose:
      - 6379
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
    environment:
      TZ: Asia/Shanghai
    # volumes:
      # 標準 Linux 系統下使用
      # - /etc/localtime:/etc/localtime:ro
      # - /etc/timezone:/etc/timezone:ro

networks:
  gogs:
    internal: true
  traefik:
    external: true
複製代碼

和配置文件搭配使用的 .env 環境變量文件內容以下:

DOCKER_GOGS_IMAGE=gogs/gogs:0.11.91
GOGS_DOMIAN=gogs.lab.com

DOCKE_MYSQL_IMAGE=mysql:5.7.16
MYSQL_HOST=mysql.gogs.lab.com

DOCKER_REDIS_IMAGE=redis:5.0-alpine
REDIS_HOST=cache.gogs.lab.com
複製代碼

Gogs 使用的 app.ini 配置文件內容:

APP_NAME = Private Repo
RUN_USER = git
RUN_MODE = prod

[database]
DB_TYPE  = mysql
HOST     = mysql.gogs.lab.com:3306
NAME     = gogs
USER     = gogs
PASSWD   = gogs
SSL_MODE = disable
PATH     = data/gogs.db

[cache]
ADAPTER=redis
INTERVAL=60
HOST=network=tcp,addr=cache.gogs.lab.com:6379,password=,db=0,pool_size=100,idle_timeout=180

[repository]
ROOT = /data/git/gogs-repositories
FORCE_PRIVATE=true
MAX_CREATION_LIMIT=-1
DISABLE_HTTP_GIT=true

[server]
DOMAIN           = gogs.lab.com
HTTP_PORT        = 3000
ROOT_URL         = https://gogs.lab.com/
DISABLE_SSH      = false
SSH_PORT         = 22
SSH_LISTEN_HOST  = 0.0.0.0
SSH_LISTEN_PORT  = 22
START_SSH_SERVER = false
OFFLINE_MODE     = true

[mailer]
ENABLED = false

[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL     = false
DISABLE_REGISTRATION   = false
ENABLE_CAPTCHA         = false
REQUIRE_SIGNIN_VIEW    = true

[picture]
DISABLE_GRAVATAR        = true
ENABLE_FEDERATED_AVATAR = false

[session]
PROVIDER=redis
PROVIDER_CONFIG=network=tcp,addr=cache.gogs.lab.com:6379,password=,db=0,pool_size=100,idle_timeout=180

[log]
MODE      = console, file
LEVEL     = Info
ROOT_PATH = /app/gogs/log

[admin]
DISABLE_REGULAR_ORG_CREATION=true

[security]
INSTALL_LOCK = true
LOGIN_REMEMBER_DAYS=true
SECRET_KEY   = pLdr79uA4YnwDab

[other]
SHOW_FOOTER_BRANDING=false
複製代碼

啓動應用

使用 docker-compose up 啓動應用,稍等片刻能夠看到日誌相似下面:

Network traefik is external, skipping
Creating network "gogs_gogs" with the default driver
Creating gogs_db_1    ... done
Creating gogs_cache_1 ... done
Creating gogs_app_1   ... done
Attaching to gogs_cache_1, gogs_db_1, gogs_app_1
cache_1  | 1:C 28 Sep 2019 15:38:57.955 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
cache_1  | 1:C 28 Sep 2019 15:38:57.955 # Redis version=5.0.6, bits=64, commit=00000000, modified=0, pid=1, just started
cache_1  | 1:C 28 Sep 2019 15:38:57.955 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
db_1     | Initializing database
db_1     | 2019-09-28T07:38:58.172565Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
db_1     | 2019-09-28T07:38:59.117064Z 0 [Warning] InnoDB: New log files created, LSN=45790
db_1     | 2019-09-28T07:38:59.264592Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
db_1     | 2019-09-28T07:38:59.281117Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 08ba4fc7-e1c3-11e9-a436-0242c0a89003.
app_1    | usermod: no changes
cache_1  | 1:M 28 Sep 2019 15:38:57.956 * Running mode=standalone, port=6379.
cache_1  | 1:M 28 Sep 2019 15:38:57.956 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
cache_1  | 1:M 28 Sep 2019 15:38:57.956 # Server initialized
cache_1  | 1:M 28 Sep 2019 15:38:57.956 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
cache_1  | 1:M 28 Sep 2019 15:38:57.956 * Ready to accept connections
db_1     | 2019-09-28T07:38:59.284542Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
db_1     | 2019-09-28T07:38:59.287236Z 1 [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
app_1    | Sep 28 07:38:59 syslogd started: BusyBox v1.30.1
... ...
... ...
db_1     | 2019-09-28T07:39:11.612027Z 0 [Note] Event Scheduler: Loaded 0 events
db_1     | 2019-09-28T07:39:11.612400Z 0 [Note] mysqld: ready for connections.
db_1     | Version: '5.7.16'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
app_1    | 2019/09/28 07:39:11 [TRACE] Custom path: /data/gogs
app_1    | 2019/09/28 07:39:11 [TRACE] Log path: /app/gogs/log
app_1    | 2019/09/28 07:39:11 [TRACE] Build Time: 2019-08-12 02:30:12 UTC
app_1    | 2019/09/28 07:39:11 [TRACE] Build Git Hash: c154721f4a8f3e24d2f6fb61e74b4b64529255c2
app_1    | 2019/09/28 07:39:11 [ INFO] Private Repo 0.11.91.0811
app_1    | 2019/09/28 07:39:11 [ INFO] Cache Service Enabled
app_1    | 2019/09/28 07:39:11 [ INFO] Session Service Enabled
app_1    | 2019/09/28 07:39:14 [ INFO] Git Version: 2.22.0
app_1    | 2019/09/28 07:39:14 [ INFO] Git config user.name set to Gogs
app_1    | 2019/09/28 07:39:14 [ INFO] Git config user.email set to gogs@fake.local
app_1    | 2019/09/28 07:39:14 [ INFO] SQLite3 Supported
app_1    | 2019/09/28 07:39:14 [ INFO] Run Mode: Production
app_1    | 2019/09/28 07:39:14 [ INFO] Listen: http://0.0.0.0:3000
app_1    | [Macaron] 2019-09-28 07:39:14: Started GET / for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:14: Completed GET / 302 Found in 2.4563ms
app_1    | [Macaron] 2019-09-28 07:39:14: Started GET /user/login for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:14: Completed GET /user/login 200 OK in 13.0259ms
app_1    | [Macaron] 2019-09-28 07:39:20: Started GET / for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:20: Completed GET / 302 Found in 1.4996ms
app_1    | [Macaron] 2019-09-28 07:39:20: Started GET /user/login for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:20: Completed GET /user/login 200 OK in 11.8768ms
app_1    | [Macaron] 2019-09-28 07:39:25: Started GET / for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:25: Completed GET / 302 Found in 1.9598ms
app_1    | [Macaron] 2019-09-28 07:39:25: Started GET /user/login for 127.0.0.1
app_1    | [Macaron] 2019-09-28 07:39:25: Completed GET /user/login 200 OK in 10.8364ms
app_1    | [Macaron] 2019-09-28 07:39:30: Started GET / for 127.0.0.1
複製代碼

訪問 gogs.lab.com 打開頁面,就能夠開始使用啦。

gogs 默認界面

備份數據

備份數據須要使用 gogs backup ,不管是在 容器內執行,仍是在容器外使用 docker exec 都是能夠的。

chown -R /backup
su git -c "/app/gogs/gogs backup -v --target /backup/"

2019/09/28 17:12:36 [ INFO] Backup succeed! Archive is located at: /app/gogs/backup/gogs-backup-20190928171236.zip
複製代碼

最後

比較巧合的是,去年九月開始,gogs 的更新開始了休眠模式,隨後它的 fork 版本 Gitea 開始了茁壯成長。

下一篇聊聊,怎麼使用 Traefik v2 TCP 模式搭建 Gitea 。

--EOF


我如今有一個小小的折騰羣,裏面彙集了一些喜歡折騰的小夥伴。

在不發廣告的狀況下,咱們在裏面會一塊兒聊聊軟件、HomeLab、編程上的一些問題,也會在羣裏不按期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼添加好友。(請註明來源和目的,不然不會經過審覈)

關於折騰羣入羣的那些事

相關文章
相關標籤/搜索