今年に入ってから自宅の環境を全部作り変えしたのだけど、その一環としてGithubのリポジトリをローカルのGitlab-CEにMirroringしてバックアップをする仕組みを取り入れてみた。

実はGitlabではGithub等とのMirroringの仕組み自体は用意されているのだが、残念ながらGitlab-CEではpushしか扱えない様になっている。 (Gitlab-EEではpush/pullどっちもできるのだが、Github-CEではpullができない(少なくとも、手元のGitlab-CE13.2.2ではダメ。))

流石に個人用に使ってるGitlabでEEを使うのはお財布的にちょっと抵抗があるので、なにか方法がないかなと調べたところ、 Github => Gitlab への転送を中継するようなスクリプトを定期実行するのが一番ラクそうだったので、それを使って実現することにした。

なお、自分の環境の場合はGitlabをdocker-composeで起動してるDockerコンテナで動作させているので、同居させてしまうことにした。 実際に動かしてるスクリプト(services.sh)がこれ。面倒だったのでtoken直書きになってるけど、環境変数にでもしたほうが良いかも。

services.sh
#!/bin/bash # 変数指定 repo_home="/src" gitlab_url="http://gitlab" gitlab_token="gitlab_no_token" github_user="user" github_token="github_no_token" # mirroring対象となるリポジトリを配列化 repo_list=( # リポジトリを配列で記述(githubのリポジトリ(from):gitlabのリポジトリ(to)) "blacknon/lssh:blacknon/lssh" "blacknon/hwatch:blacknon/hwatch" ) # SSLのエラーを無視するように指定 git config --global http.sslVerify false cd "${repo_home}" while true; do for repo in ${repo_list[@]}; do # repo_listからGithub/GitlabそれぞれのRepositoryを取得 github_repo="${repo%:*}" gitlab_repo="${repo#*:}" repo_local=$(basename ${github_repo}) # ローカルリポジトリが無い場合、githubから取得する if [ ! -d "${repo_home}/${repo_local}" ]; then git clone --bare --mirror https://${github_user}:${github_token}@github.com/${github_repo} ${repo_local} fi ( cd "${repo_home}/${repo_local}" git fetch --prune git push --prune https://gitlab-ci-token:${gitlab_token}@gitlab.local/${gitlab_repo} +refs/heads/*:refs/heads/* +refs/tags/*:refs/tags/* ) # 1リポジトリごとの待機(3秒) sleep 3 done # 1ループ全体の待機時間(60秒) sleep 60s done

使ってるdocker-compose.ymlはこんな感じ。

docker-compose.yml
version: "2" services: # リバースプロキシ(ssl用)のコンテナ(今回は特に関係ない) nginx-proxy: image: jwilder/nginx-proxy container_name: nginx-proxy ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./certs:/etc/nginx/certs environment: TZ: Asia/Tokyo # gitlab用のコンテナ gitlab: container_name: gitlab image: gitlab/gitlab-ce:latest restart: always ports: - "10022:22" volumes: - "/opt/data/gitlab/conf:/etc/gitlab" - "/opt/data/gitlab/data:/var/opt/gitlab" environment: GITLAB_OMNIBUS_CONFIG: | external_url 'https://gitlab.local/' nginx['listen_port'] = 80 nginx['listen_https'] = false gitlab_rails['time_zone'] = 'Asia/Tokyo' gitlab_rails['gitlab_shell_ssh_port'] = 10022 VIRTUAL_HOST: gitlab.local VIRTUAL_PORT: 80 CERT_NAME: default # gitlab-runner用のコンテナ(今回は特に関係ない) runner: image: 'gitlab/gitlab-runner:latest' restart: always container_name: runner volumes: - "/opt/data/runner/config:/etc/gitlab-runner" - "/var/run/docker.sock:/var/run/docker.sock" - ./runner/cacert.pem:/opt/cacert.pem gitsync: build: ./gitsync container_name: gitsync restart: always tty: true volumes: - "/opt/data/gitsync/src:/src" - "/opt/gitlab/gitsync/.ssh:/root/.ssh"

Dockerfileは↓みたいな感じ。

FROM python:2.7-alpine3.7

ENV PBR_VERSION=1.5.6

RUN set -x \
    && apk upgrade --update \
    && apk add \
    bash \
    coreutils \
    curl \
    git

WORKDIR /src

COPY . .

COPY services.sh /usr/local/bin/services.sh

CMD ["/usr/local/bin/services.sh"]

whileでloopさせるやり方で、かつシングルタスクになってるからあまり効率は良くないかもしれないけど、ひとまず目的は達せられそう。 (マルチで流すことも一応できるけど)

Gitlab-CEでもpull mirroringが使えるようになると良いけど、どうかなぁ・・・。