mike-neckのブログ

Java or Groovy or Swift or Golang

ArtifactoryのDockerイメージとgradleでのartifactのデプロイのメモ

少々こまったことがあったので、Artifactoryを調べたので、そのメモ。なお、数年前も同じことを調べたという記憶があるのだが、メモを残していなかったのであらたに調べることになった…


書かれていること

  • ArtifactoryのイメージをビルドするDockerfile
  • プロジェクトの成果物をpublishする場合のビルドファイル
  • Artifactoryにpublishしたjarファイルをプロジェクトで利用する場合のビルドファイル

ArtifactoryのイメージをビルドするDockerfile

作りたいArtifactoryのDockerイメージは次のようなもの

  • なるべく小さいイメージにしたい
  • データベースにデフォルトで有効になっているderbyではなく、mysqlを利用する
  • ポート番号をデフォルトの8081は使いたくないので5000にする
  • データベースのスキーマ/ユーザー/パスワードは環境変数によって設定可能にする

Artifactoryではデータベースの接続設定はファイルから読み込む形になっているが、これを起動時の環境変数により修正するためDockerfileだけではなく(もちろんDockerfileで完結させることはできる)、別途シェル(entry-point.sh)を用意した。

Dockerfile

FROM openjdk:8u111-jre-alpine

ENV ARTIFACTORY_VERSION 5.1.0
ENV ARTIFACTORY_HOME    /artifactory-oss-${ARTIFACTORY_VERSION}

ENV ARTIFACTORY_PORT    5000

ADD entry-point.sh /entry-point.sh

RUN apk --no-cache add curl bash && \
  curl -SL "https://bintray.com/jfrog/artifactory/download_file?file_path=jfrog-artifactory-oss-${ARTIFACTORY_VERSION}.zip" > artifactory.zip && \
  unzip -q artifactory.zip && \
  rm artifactory.zip && \
  curl -SL "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.zip" > mysql-connector.zip && \
  unzip -q mysql-connector.zip && \
  rm mysql-connector.zip && \
  apk --no-cache del curl && \
  mv mysql-connector-java-5.1.40/mysql-connector-java-5.1.40-bin.jar ${ARTIFACTORY_HOME}/tomcat/lib/ && \
  rm -rf mysql-connector-java-5.1.40/ && \
  mkdir ${ARTIFACTORY_HOME}/data && \
  mv ${ARTIFACTORY_HOME}/tomcat/conf/server.xml ${ARTIFACTORY_HOME}/tomcat/conf/tmp.xml && \
  cat ${ARTIFACTORY_HOME}/tomcat/conf/tmp.xml | \
    sed -e "s/8081/${ARTIFACTORY_PORT}/g" > \
    ${ARTIFACTORY_HOME}/tomcat/conf/server.xml && \
  rm ${ARTIFACTORY_HOME}/tomcat/conf/tmp.xml && \
  chmod +x /entry-point.sh

VOLUME ["${ARTIFACTORY_HOME}/data"]
EXPOSE ${ARTIFACTORY_PORT}

CMD     ["/entry-point.sh"]

entry-point.sh

#!/bin/bash

set -eu

if [ ! -v ARTIFACTORY_HOME ]; then
    echo ARTIFACTORY_HOME is not set
    exit 1
fi

if [ ! -v DB_ADDRESS ]; then
  DB_ADDRESS=db
fi

if [ ! -v DB_PORT ]; then
    DB_PORT=3306
fi

provider_types=("filesystem" "fullDb" "cachedFS")

if [ ! -v PROVIDER_TYPE ]; then
  PROVIDER_TYPE=filesystem
elif [[ ! ${provider_types} =~ (^|[[:space:]])${PROVIDER_TYPE}([[:space:]]|$) ]]; then
  PROVIDER_TYPE=filesystem
fi

if [ ! -v PROVIDER_SIZE ]; then
    PROVIDER_SIZE=1GB
fi

cat << EOF > ${ARTIFACTORY_HOME}/etc/db.properties
type=mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://${DB_ADDRESS}:${DB_PORT}/${DB_NAME}?characterEncoding=UTF-8&elideSetAutoCommits=true
username=${DB_USER}
password=${DB_PASSWORD}
binary.provider.type=${PROVIDER_TYPE}
binary.provider.cache.maxSize=${PROVIDER_SIZE}
EOF

${ARTIFACTORY_HOME}/bin/artifactory.sh

あとは次のような docker-compose.yml を作って起動すればよい

version: '2'
services:
  db:
    image: mysql:5.7
    environment:
      - MYSQL_DATABASE=artifactory
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - MYSQL_RANDOM_ROOT_PASSWORD=yes
    ports:
      - 3306:3306
  artifactory:
    build: ./artifactory
    environment:
      - DB_NAME=artifactory
      - DB_USER=user
      - DB_PASSWORD=password
    volumes:
      - ./artifactory/data:/artifactory-oss-5.1.0/data
    depends_on:
      - db
    ports:
      - 5000:5000

そうすると、ローカルで実行した場合は http://localhost:5000/artifactory にアクセスすると Artifactory を開くことができる。なお、デフォルトのユーザーとパスワードがadmin/password。とりあえず、デフォルトのユーザーは使えなくして、別のユーザーを作成する。


プロジェクトの成果物をpublishする

次のようにレポジトリーにあげたい

  • Artifactoryのkey gradle-dev-local
  • あげるファイル
    • pom
    • 成果物のjar
    • ソースのjar
    • javadocのjar

build.gradle は次のとおり

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
  }
}

apply plugin: 'java'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"

group = 'com.example'
version = '0.1'

repositories {
  mavenCentral()
}

dependencies {
  compileOnly     'org.jetbrains:annotations:15.0'
  compileOnly     'org.projectlombok:lombok:1.16.14'
  compile         'javax.inject:javax.inject:1'
}

task sourceJar(type: Jar) {
  from sourceSets.main.allSource
  classifier = 'sources'
}

task javadocJar(type: Jar) {
  from tasks.javadoc
  classifier = 'javadoc'
}

artifactory {
  contextUrl = 'http://localhost:5000/artifactory'
  publish {
    repository {
      repoKey = 'gradle-dev-local'
      username = "user"
      password = "password"
      maven = true
    }
    defaults {
      publications('javaProject')
      publishArtifacts = true
      publishPom = true
    }
  }
  resolve {
    repository {
      repoKey = 'gradle-dev'
      username = "user"
      password = "password"
      maven = true
    }
  }
}

publishing {
  publications {
    javaProject(MavenPublication) {
      from components.java
      artifacts = [sourceJar, javadocJar, jar]
    }
  }
}

これによって、artifactoryPublish タスクによって Artifactoryにpublishできるようになる。なお、ポイントとしては次のとおり

  • ArtifactoryにてRepository BrowserのSet Me Upからビルドファイルの雛形を吐き出してくれるが、 maven-publish の記述がないので、そのままでは何もできない。またusername/password用にGStringで何かやってくれているプロパティファイルを吐き出してくれるが、残念ながらプロパティファイルはそのまま文字列になるので何にもならない。
  • maven-publish プラグインにてpublishの準備が整えられたartifactを artifactoryのpublicationsに指定する(上記の javaProject と書いてあるやつ)

なお、こちらのページを参考にした、というかほとんどコピーした…

kinjouj.github.io


Artifactoryにpublishしたjarファイルをプロジェクトで利用する

次のようなビルドファイルを用いる

repositories {
  maven {
    url "http://localhost:5000/artifactory/gradle-dev-local"
  }
}

dependencies {
  compile 'com.example:sample-java-project:0.1'
}

以上