概要

Drone の pipeline から 同一ホスト上で稼働する別のコンテナの再起動などを行ったみた。

目次

必要な設定

drone のパイプラインから 他の docker コンテナの停止や起動などを行う場合、以下の設定が必要となる。

/var/run/docker.sock のマウント

runner で /var/run/docker.sock を参照できる必要があるので為、以下の通り /var/run/docker.sock をマウントしておく。
尚、.drone.yml で volumes を使用するには、Droneの設定で対象リポジトリを信頼済み(Trusted)としておく必要がある。(この操作はDroneの管理者ユーザのみ可能)
DroneでAzureリソースをデプロイする(注意点)

kind: pipeline
type: docker
name: default

steps:
- name: "build and push to registry"
  image: docker/compose
  volumes:
  - name: dockersock
    path: /var/run/docker.sock
  commands:
    :

volumes:
- name: dockersock
  host:
    path: /var/run/docker.sock

docker login

プライベートなレジストリへの push や pull を行う前の docker login では コマンドにパスワードを含まない用に考慮する。
https://docs.docker.com/engine/reference/commandline/login/#provide-a-password-using-stdin に記載されている方法に習う場合、ホスト側に置いたパスワードファイルもマウントしておく。

kind: pipeline
type: docker
name: default

steps:
- name: "build and push to registry"
  image: docker/compose
  volumes:
  - name: registrypwd
    path: /tmp/registry-password
  commands:
  # プライベートレジストリに docker login (パスワードはホスト側のファイルから取得)
  - "cat /tmp/registry-password | docker login ${REGISTRY_NAME} --username ${REGISTRY_USER} --password-stdin"
    :

volumes:
- name: registrypwd
  host:
    path: /path/to/registry-password

サンプル

環境イメージ

Azure 上に 以下の環境を作って検証してみた。

azure_drone_image_vm_ver.png

環境作成

#!/bin/bash

PREFIX=XXXXXXX
subscriptionId=XXXXXXXXXXXXXXXXXXXXXXXXXX
region=japanwest

# リソースグループ
resourceGroup=${PREFIX}Resources

# 仮想ネットワーク
vnetName=${PREFIX}VNet
vnetPrefix=10.1.0.0/16

# セキュリティグループ名
nsgName=${vnetName}SecGrp
nsgPubRuleName=${nsgName}PubRule

# 仮想マシンを配置するサブネット
vmSubnetName=${PREFIX}VmSubnet
vmSubnetPrefix=10.1.1.0/24

# 仮想マシンの情報
vmName=${PREFIX}Vm
vmImage=UbuntuLTS
vmIpAddress=10.1.1.5
vmUser=sample

# コンテナレジストリ名(Prefix)
registryName=${PREFIX}registry
#!/bin/bash

# 設定の読み込み
source 0_env.sh

# リソース作成
if [ "$1" == "--create" ]; then

  # リソースグループの作成
  echo "az group create"
  az group create --name $resourceGroup --location $region

  # NSG(ネットワークセキュリティグループの)作成
  echo "az network nsg create"
  az network nsg create --resource-group $resourceGroup --name $nsgName

  # NSGルール(80番ポート)
  echo "az network nsg rule create(80)"
  az network nsg rule create \
    --resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}1\
    --access Allow --protocol Tcp --direction Inbound --priority 100 \
    --source-address-prefix Internet --source-port-range "*" --destination-port-range "80"

  # NSGルール(443番ポート)
  echo "az network nsg rule create(443)"
  az network nsg rule create \
    --resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}2 \
    --access Allow --protocol Tcp --direction Inbound --priority 101 \
    --source-address-prefix Internet --source-port-range "*" --destination-port-range "443"

  # NSGルール(22ポート)
  echo "az network nsg rule create(ssh)"
  az network nsg rule create \
    --resource-group $resourceGroup --nsg-name $nsgName --name ${nsgPubRuleName}3 \
    --access Allow --protocol Tcp --direction Inbound --priority 1000 \
    --source-address-prefix Internet --source-port-range "*" --destination-port-range "22"

  # 仮想ネットワーク 及び サブネット作成
  echo "az network vnet create"
  az network vnet create \
    --name $vnetName --resource-group $resourceGroup \
    --address-prefixes $vnetPrefix --network-security-group $nsgName \
    --subnet-name $vmSubnetName --subnet-prefixes $vmSubnetPrefix

  # コンテナレジストリ作成
  echo "az acr create ( $registryName )"
  az acr create -n $registryName -g $resourceGroup --sku standard --admin-enabled true

  # レジストリユーザ名/パスワード取得
  acr_credential="`az acr credential show --name $registryName -o table | tail -1`"
  registryUser="`echo "$acr_credential" | awk '{print $1}'`"
  registryPwd="`echo "$acr_credential" | awk '{print $2}'`"

  # 初版のDockerイメージをビルドしてACRに登録
  #echo "az acr build ( $appImageName )"
  #echo az acr build --registry $registryName --image ${appImageName} -f ./sample-app1/Dockerfile ./sample-app1
  #az acr build --registry $registryName --image ${appImageName} -f ./sample-app1/Dockerfile ./sample-app1

  # VMセットアップスクリプト作成(環境変数を埋め込み)
  cat 2_setup_vm.tmpl \
      | sed "s/###REGISTRY_USER###/${registryUser}/g" \
      | sed "s/###REGISTRY_PWD###/${registryPwd}/g" > 2_setup_vm.sh
  chmod 755 2_setup_vm.sh

  # 仮想マシンの作成
  rm -rf  ~/.ssh/id_rsa
  rm -rf  ~/.ssh/id_rsa.pub
  echo "az vm create"
  az vm create \
    --resource-group $resourceGroup --name $vmName --image $vmImage --generate-ssh-keys \
    --vnet-name $vnetName --subnet $vmSubnetName \
    --private-ip-address $vmIpAddress --admin-username $vmUser \
    --public-ip-address-dns-name `echo $vmName | tr '[A-Z]' '[a-z]'` \
    --custom-data 2_setup_vm.sh

  # ポート開放
  echo "az vm open-port(80)"
  az vm open-port --resource-group $resourceGroup --name $vmName --port 80 --priority 901
  echo "az vm open-port(443)"
  az vm open-port --resource-group $resourceGroup --name $vmName --port 443 --priority 902

  # 生成されたSSH鍵を退避しておく
  mkdir -p pem
  if [ -e ~/.ssh/id_rsa ]; then
    mv ~/.ssh/id_rsa     ./pem/id_rsa_${vmName}
    mv ~/.ssh/id_rsa.pub ./pem/id_rsa_${vmName}.pub
  fi

  # giteaのURLを表示
  echo GITEA      ... https://${vmName}.${region}.cloudapp.azure.com/gitea | tr [A-Z] [a-z]
  echo DRONE      ... https://${vmName}.${region}.cloudapp.azure.com | tr [A-Z] [a-z]
  echo Sample App ... https://${vmName}.${region}.cloudapp.azure.com/sample-app1 | tr [A-Z] [a-z]
fi

# リソース削除
if [ "$1" == "--delete" ]; then
  echo az group delete
  az group delete --name $resourceGroup
fi

# URL表示
if [ "$1" == "--env" ]; then
  echo GITEA      ... https://${vmName}.${region}.cloudapp.azure.com/gitea | tr [A-Z] [a-z]
  echo DRONE      ... https://${vmName}.${region}.cloudapp.azure.com | tr [A-Z] [a-z]
  echo Sample App ... https://${vmName}.${region}.cloudapp.azure.com/sample-app1 | tr [A-Z] [a-z]
fi
#!/bin/bash

apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

# set server name
region=japanwest
hostname=`hostname | tr [A-Z] [a-z]`
server_name="${hostname}.${region}.cloudapp.azure.com"


# make and change directory
mkdir -p /tmp/docker_container
cd /tmp/docker_container

#--------------------------------------
# wait until azure dns name is available.
# (If it is NG after waiting 5 minutes, give up..)
#--------------------------------------
for i in `seq 30`; do
  x=`host $server_name`
  if [ "$?" == "0" ]; then
    break
  fi
  sleep 10
done

#--------------------------------------
# get ssl certificate.
#--------------------------------------
sudo docker run --rm -p 80:80 \
    -v /etc/letsencrypt:/etc/letsencrypt \
    -v /etc/letsencrypt/logs:/var/log/letsencrypt \
    certbot/certbot certonly --standalone \
    -d $server_name \
    --register-unsafely-without-email \
    --non-interactive --agree-tos \
    --force-renewal \
    --renew-by-default \
    --preferred-challenges http

#--------------------------------------
# create default.conf for nginx.
#--------------------------------------
cat <<_EO_DEFAULT_CONF_>default.conf
# http
server{
    listen 80;
    listen [::]:80;
    server_name ${server_name};
    return 301 https://\$host\$request_uri;
}

# https
server{
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name  ${server_name};
    ssl_certificate     /etc/letsencrypt/live/${server_name}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${server_name}/privkey.pem;

    location /sample-app1/ {
        proxy_pass http://sample-app1/;
    }

    location /gitea/ {
        proxy_pass http://gitea-app:3000/;
    }

    location / {
        proxy_pass http://drone-app/;
    }
}
_EO_DEFAULT_CONF_

#--------------------------------------
# set REGISTRY_NAME to environments.
#--------------------------------------
#export REGISTRY_NAME=###REGISTRY_USER###.azurecr.io


#--------------------------------------
# make .env
#--------------------------------------
cat <<_EO_ENV_>.env
GITEA_HOST=${server_name}
GITEA_USER_GID=1000
GITEA_USER_UID=1000
GITEA_DB_HOST=gitea-db:5432
GITEA_DB_NAME=gitea
GITEA_DB_PASSWD=gitea
GITEA_DB_PASSWORD=gitea
GITEA_DB_USER=gitea
DRONE_HOST=${server_name}
DRONE_GITEA_CLIENT_ID=
DRONE_GITEA_CLIENT_SECRET=
DRONE_RPC_SECRET=secret
DRONE_RUNNER_CAPACITY=2

REGISTRY_NAME=###REGISTRY_USER###.azurecr.io
REGISTRY_USER=###REGISTRY_USER###
_EO_ENV_


#--------------------------------------
# registry password.
#--------------------------------------
echo "###REGISTRY_PWD###">registry-password


#
# make docker-compose.yml
#
cat <<_EO_DOCKER_COMPOSE_>docker-compose.yml
version: "3"

services:
  gitea-proxy:
    image: nginx:latest
    hostname: gitea-proxy
    container_name: gitea-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
      - /etc/letsencrypt:/etc/letsencrypt
    links:
      - gitea-app
    depends_on:
      - gitea-app

  gitea-app:
    image: gitea/gitea:latest
    hostname: gitea-app
    container_name: gitea-app
    environment:
      USER_UID: "\${GITEA_USER_UID}"
      USER_GID: "\${GITEA_USER_GID}"
      ROOT_URL: "https://\${GITEA_HOST}/gitea"
      DB_TYPE: "postgres"
      DB_HOST: "\${GITEA_DB_HOST}"
      DB_NAME: "\${GITEA_DB_NAME}"
      DB_USER: "\${GITEA_DB_USER}"
      DB_PASSWD: "\${GITEA_DB_PASSWD}"
      DISABLE_SSH: "true"
      #SSH_DOMAIN: "\${GITEA_HOST}"
      #SSH_PORT: "\${GITEA_SSH_PORT}"
      SKIP_TLS_VERIFY: "true"
      TZ: "Japan"
    volumes:
      - ./volumes/gitea-app:/data
    links:
      - gitea-db

  gitea-db:
    image: postgres:latest
    hostname: gitea-db
    container_name: gitea-db
    volumes:
      - ./volumes/gitea-db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: "\${GITEA_DB_NAME}"
      POSTGRES_USER: "\${GITEA_DB_USER}"
      POSTGRES_PASSWORD: "\${GITEA_DB_PASSWD}"

  drone-app:
    image: drone/drone:latest
    hostname: drone-app
    container_name: drone-app
    environment:
    links:
      - gitea-app
    depends_on:
      - gitea-app
    environment:
      DOCKER_API_VERSION: "1.39"
      DRONE_AGENT_ENABLED: "true"
      DRONE_GITEA_SERVER: "https://\${GITEA_HOST}/gitea"
      DRONE_GITEA_CLIENT_ID: "\${DRONE_GITEA_CLIENT_ID}"
      DRONE_GITEA_CLIENT_SECRET: "\${DRONE_GITEA_CLIENT_SECRET}"
      DRONE_RPC_SECRET: "\${DRONE_RPC_SECRET}"
      DRONE_SERVER_HOST: "\${DRONE_HOST}"
      DRONE_SERVER_PROTO: "https"
      DRONE_USER_CREATE: "username:droneadmin,admin:true"
      DRONE_GITEA_SKIP_VERIFY: "true"
      DRONE_GITEA_ALWAYS_AUTH: "false"
      DRONE_TLS_AUTOCERT: "false"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./volumes/drone-app:/var/lib/drone

  drone-runner:
    image: drone/drone-runner-docker:latest
    hostname: drone-runner
    container_name: drone-runner
    links:
      - drone-app
      - gitea-app
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./.env:/etc/drone.env:ro
    environment:
      DOCKER_API_VERSION: "1.39"
      DRONE_RPC_PROTO: "https"
      #DRONE_RPC_HOST: "\${DRONE_HOST}:\${DRONE_PORT}"
      DRONE_RPC_HOST: "\${DRONE_HOST}"
      DRONE_RPC_SECRET: "\${DRONE_RPC_SECRET}"
      DRONE_RUNNER_CAPACITY: "\${DRONE_RUNNER_CAPACITY}"
      DRONE_RUNNER_NAME: "drone-runner"
      DRONE_RUNNER_ENV_FILE: "/etc/drone.env"
      DRONE_TRACE: "true"
      DRONE_RPC_DUMP_HTTP: "true"
      DRONE_RPC_DUMP_HTTP_BODY: "true"
      #DRONE_RUNNER_NETWORKS: my-network

networks:
  default:
    external:
      name: my_network
_EO_DOCKER_COMPOSE_

#--------------------------------------
# create docker network
#--------------------------------------
docker network create my_network

#--------------------------------------
# start sample-app1(dummy).
#--------------------------------------
docker run --rm --network my_network --hostname sample-app1 --name sample-app1 -d nginx

#--------------------------------------
# start ci/cd containers
#--------------------------------------
docker-compose up -d

(1) Azure環境の作成

./1_create_vm.sh --create
 :
 :
gitea ... https://xxxxxxxxx.japanwest.cloudapp.azure.com/gitea
drone ... https://xxxxxxxxx.japanwest.cloudapp.azure.com
sample app ... https://xxxxxxxxx.japanwest.cloudapp.azure.com/sample-app1

(2) Gitea セットアップ

  • 表示された Gitea のURLにアクセスして初期セットアップ
  • OAuthアプリケーション登録、及び サンプルアプリ用のリポジトリ作成
  • VM に sshログインし .env のクライアントシークレットID、キーを変更
     ※ ssh鍵は ./pem配下に出来ている筈
     ※ VMの IP は az vm list-ip-addresses -o table で確認。
     ※ .env や docker-compose.yml は /tmp/docker_container 配下に出来ている筈。

 ※ Gitea&DroneでCI/CD環境構築#zf9f5c8d を参照。

(3) Droneコンテナ再作成

docker-compose stop && docker-compose up --build -d

(4) Drone の URL にアクセスしてサンプルアプリ用のリポジトリをActivate
 ※ Gitea&DroneでCI/CD環境構築#xdb9d209 を参照。

サンプルアプリの作成

上記で作成したサンプルアプリ用のリポジトリに以下のリソースを commit、push して Drone のパイプラインが正常に実行された事を確認後に、sample app の URLにアクセスして画面が表示( version 1 )されたらOK。

FROM nginx
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
version: "3" 
  
services:
  sample-app1:
    image: ${REGISTRY_NAME}/sample-app1:latest
    hostname: sample-app1
    container_name: sample-app1
    #ports:
    #  - "8000:80"

networks:
  default:
    external:
      name: my_network
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>

<h1>Sample App1!</h1>

<div>version 1.</div>

</body>
</html>
kind: pipeline
type: docker
name: default

steps:
- name: "build and push to registry"
  image: docker/compose
  volumes:
  - name: dockersock
    path: /var/run/docker.sock
  - name: containers
    path: /tmp/docker_container
  commands:
  - "nowdate=`date +%Y%m%d_%H%M%S`"
  - "appname=sample-app1"
  - "cat /tmp/docker_container/registry-password | docker login ${REGISTRY_NAME} --username ${REGISTRY_USER} --password-stdin"
  - "docker build -t $appname ."
  - "docker tag $appname $REGISTRY_NAME/$appname:latest"
  - "docker tag $appname $REGISTRY_NAME/$appname:$nowdate"
  - "docker push $REGISTRY_NAME/$appname:latest"
  - "docker push $REGISTRY_NAME/$appname:$nowdate"
  when:
    branch:
    - master
- name: "docker pull and restart"
  image: docker/compose
  volumes:
  - name: dockersock
    path: /var/run/docker.sock
  - name: containers
    path: /tmp/docker_container
  commands:
  - "appname=sample-app1"
  - "cat /tmp/docker_container/registry-password | docker login ${REGISTRY_NAME} --username ${REGISTRY_USER} --password-stdin"
  - "if [ `docker ps | grep $appname | wc -l` != \"0\" ]; then docker stop $appname ; fi"
  - "if [ `docker ps -a | grep $appname | wc -l` != \"0\" ]; then docker rm $appname ; fi"
  - "if [ `docker images | grep ${REGISTRY_NAME}/${appname}:latest | wc -l` != \"0\" ]; then docker rmi ${REGISTRY_NAME}/${appname}:latest; fi"
  - "docker-compose up --build -d"
  when:
    branch:
    - master

volumes:
- name: dockersock
  host:
    path: /var/run/docker.sock
- name: containers
  host:
    path: /tmp/docker_container

添付ファイル: fileazure_drone_image_vm_ver.png 1件 [詳細]

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-09-11 (金) 18:20:03 (11d)