Windows 10からRaspberry PiにSSH接続してみる(公開鍵認証)

はじめに

Raspberry Piを操作するのに、ディスプレイをつないでいたら面倒です。そこで、SSH接続により他のPCからRaspberry Piに接続する方法をメモしておきたいと思います。また、よりセキュアな通信を行うために、BASIC認証ではなく、公開鍵認証にて接続を行います。

1. SSHの設定(Raspberry Pi側)

ブートディレクトリにSSHディレクトリを用意します。

sudo touch /boot/ssh

次に、[設定] -> [Raspberry Piの設定]からSSH有効にしておきます。

image.png (114.2 kB)

リブート後、以下のような警告メッセージが出る場合、パスワードが初期値になっているので、変更しておきましょう。

image.png (55.3 kB)

ちなみに、デフォルトでは以下のUserとPasswordになっています。

User Password
pi raspberry

[設定] -> [Raspberry Piの設定]からパスワードの変更を行えます。

image.png (143.4 kB)

以上でRaspberry Pi側の設定は終わりです。

2. Windows 10からRaspberry PiSSH接続する(Windows 10側)

今回は、WinSCPを使って接続してみたいと思います。 WinSCPをインストールしていない場合は、以下からダウンロード&インストール。

winscp.net

ホスト名にRaspberry Pi側のIPアドレス、ユーザ名とパスワードを設定し、ログインボタンをクリックします。

image.png (24.7 kB)

すると、以下のように接続できていると思います。

image.png (85.3 kB)

以上で、Windows 10側からのBASIC認証によるSSH接続は完了です。

3. 公開鍵認証でSSH接続

BASIC認証だとセキュアとは言えないので、今回は公開鍵認証でSSH接続する方法についても言及します。

Windows 10側

まず、Windows 10側で公開鍵と秘密鍵のペアを作ります。

OpenSSHを使おうと思うので、Gitがインストールされていることを前提としています。 Gitをインストールしていない場合は、以下からダウンロード&インストール。

https://git-scm.com/

Git Bashから、以下のコマンドを実行します。 メールアドレスについては任意の値でOKです。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

保存先やパスワードの入力を求められますが、何も入力せずにEnterします。 すると、C:\Users\ユーザ名\.ssh直下に * id_sra (秘密鍵) * id_rsa.pub (公開鍵)

が作成されます。

image.png (105.1 kB)

WinSCPで公開鍵であるid_rsa.pubRaspberry Pi側に転送しておきます。

image.png (111.8 kB)

Raspberry Pi

先ほど転送した公開鍵をRaspberry Pi側に登録します。

# ホームディレクトリへ移動
cd /home/pi

# 公開鍵をRaspberry Pi側に登録
mkdir .ssh
cat id_rsa.pub >> .ssh/authorized_keys

# 権限を設定
chmod 700 .ssh
chmod 600 .ssh/authorized_keys

SSHの設定ファイルを開きたいのですが、nanoやVimでもいいのですが、編集しやすいVSCodeを使います。まず、VSCodeをインストールしておきます。

# VSCodeのインストール
wget -O - https://code.headmelted.com/installers/apt.sh | sudo bash

# VSCodeの実行
code-oss

次に、SSH設定ファイルを開きます。

# 一時的に権限を変更
sudo chmod 666 /etc/ssh/sshd_config

# VSCodeで開く
code-oss /etc/ssh/sshd_config

(1) 公開鍵認証の設定

以下の2つについて、コメントアウトしているのは解除し、PubKeyAuthenticationyesに書き換えます。

PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
AuthorizedKeysFile  .ssh/authorized_keys .ssh/authorized_keys2

(2) BASIC認証をできないようにする

コメントアウトしているのは解除し、PasswordAuthenticationnoに書き換えます。

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no

(3) Rootログインをできないようにする

コメントアウトしているのは解除し、PermitRootLoginnoに書き換えます。

PermitRootLogin no

SSHを再起動し、上記の設定を反映させます。

# 権限をもとに戻す
sudo chmod 644 /etc/ssh/sshd_config

# SSHの再起動
sudo /etc/init.d/ssh restart

Raspberry Pi側の作業を以上で終了です。

最後に、WinSCP秘密鍵を設定し、Raspberry Piに接続できるかどうか確認して見ましょう。 設定をクリックします。

image.png (25.2 kB)

SSHの認証から、秘密鍵を設定します。ppkしか対応していないと言われるので、素直にppkファイルに変換します。

image.png (31.2 kB)

設定を保存し、ログインします。公開鍵認証がうまく行っていれば、以下のようにSSH接続できているはずです。

image.png (66.7 kB)

参考

Raspberry Piに公開鍵認証を使ってssh接続する
https://tool-lab.com/2013/11/raspi-key-authentication-over-ssh/
[wip] Raspberry Piのセキュリティを高めてみた
https://qiita.com/yyano/items/126cff2e3c49b0006c43

Windows10パソコン上にGitサーバを立ててみた - LinuxサーバがないけどGitサーバを運用したい場合の対処法

はじめに

会社や研究室でGitを使ったバージョン管理システムを構築したいというニーズが少なからずあると思います。言うまでもなく、ソースコードやそれに付随する書類を管理する上で、手作業でそれを行うのは非常に非効率だからです。

今回は、Linuxサーバを持っておらず、Windows OSの入ったパソコンしか使えない場合を想定して、Windows10パソコン上にGitサーバをたてる方法について説明します。

WindowsパソコンにGitサーバを立てることはまずやらないためか、ネット上での情報が少なく、公開されている情報も断片的だと感じたので、今回私なりにまとめてみることにしました。

実行環境

  • Gitサーバ (Windows10 Pro)
  • Gitクライアント (Windows10 Pro)

Gitのインストール(サーバ・クライアント共通)

サーバ(Windows10)とクライアント側(Windows)の両方の環境にGitをインストールします。

まず、以下のGitのサイトからGitのインストーラをダウンロードしてきます。
https://git-scm.com/

image.png (714.5 kB)

デフォルトのままで「Next」をクリックします。

image.png (20.3 kB)

Gitで使うデフォルトのテキストエディタを選択します。Windows環境なので、無難にVisual Studio Codeを選択しておきます(事前にVSCodeをインストールしておく必要があるかもしれません)。

image.png (19.8 kB)

GitコマンドをGit BashだけでなくWindowsコマンドプロンプトでも利用できるようにするか聞かれます。今回は、コマンドプロンプトでも利用できるように、真ん中のUse Git from the Windows Command Promptを選択しました。

image.png (25.9 kB)

HTTPSによる転送をどの方法で行うか聞かれます。今回は、OpenSSLを使うことにし、Use the OpenSSL libraryを選択しました。

image.png (19.1 kB)

コミット後、ソースコードUnixの改行コードに変換するかどうか聞かれます。今回は、Windowsで利用することを想定しているので、Checkout as-is, commit as-isを選択しました。

ただし、MacOSLinux OSでも利用することを想定している場合は、Checkout as-is, commit Unix-style line endingsにしておき、Unixの改行コードに統一しておくのが良いと思います。

image.png (26.1 kB)

デフォルトのままで「Next」をクリックします。

image.png (25.1 kB)

デフォルトのままで「Install」をクリックします。

image.png (24.2 kB)

以上でインストールは完了です。

クライアント側の設定

まずは、クライアント側で作業を行います。

1. Gitのグローバル設定

Git Bashもしくはコマンドプロンプトを開き、以下のコマンドを実行します。メールアドレスとユーザ名については任意の値を設定してください。

# ユーザ設定
git config --global user.email "administrator@example.com"
git config --global user.name "Administrator"

# 日本語名を表示するための設定
git config --global core.quotepath false

# Windows から git プロトコルで push するとハングアップするのを防止
git config --global sendpack.sideband false

2. SSHキーの用意

今回はGitプロトコルによる通信ではなく、SSHによる通信方法を使います。理由は、Gitプロトコルでの通信だと専用のポート (9418)を使っての通信になり、環境によっては ウイルス対策ソフトのファイアウォールに引っかかるためです。また、Gitプロトコルの場合、Windows環境ではリポジトリのクローン時にエラー(Index-pack failed)が発生することがあると確認しています。

Gitサーバの通信プロトコルについての詳細は以下を参照のこと。
https://git-scm.com/book/ja/v1/Git-サーバー-プロトコル

クライアント側でSSHキー(公開鍵と秘密鍵)を作成しておきます。-Cオプションで指定しているメールアドレスは任意のものを設定してください。

以下ではGit Bashで実行した際のコマンドを示しました。以下のssh-keygenコマンドを実行します。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

実行すると、id_rsaid_rsa.pubという2つのファイルが生成されているはずです。
このうち、公開鍵であるid_rsa.pubは、サーバ側にわたす必要があります。

サーバ側の設定

ここからはサーバ側の操作になります。

1. Gitのグローバル設定

クライアント側のときと同様に、Git Bashもしくはコマンドプロンプトを開き、以下のコマンドを実行します。メールアドレスとユーザ名については任意の値を設定してください。

# ユーザ設定
git config --global user.email "administrator@example.com"
git config --global user.name "Administrator"

# 日本語名を表示するための設定
git config --global core.quotepath false

# Windows から git プロトコルで push するとハングアップするのを防止
git config --global sendpack.sideband false

2. リポジトリを作成する

以下の場所(もちろん、任意の場所で構いません)に、リモートレポジトリを作成していきます。

フォルダの種類 サンプルパス
ベースフォルダ C:\repos
リモートリポジトリ C:\repos\sample.git

以下では、Git Bashでの操作を示しました。Cドライブの直下にレポジトリ用のフォルダを用意します。

mkdir /c/repos
mkdir /c/repos/sample.git

image.png (13.0 kB)

ベアリポジトリ(作業ディレクトリを持たないリポジトリ)を作成します。

# リポジトリの初期化
cd /c/repos/sample.git
git init --bare --shared

# Gitプロトコル時に共有レポジトリとして認識させる
touch git-daemon-export-ok

image.png (60.6 kB)

ベアリポジトリについては以下を参照のこと。
ベアリポジトリとノンベアリポジトリ:理論編〜GitでWordpressのテーマを管理
http://www.nekotricolor.com/entry/theory-of-bare-and-non-bare-repository-manage-wordpress-themes-with-git

3. SSH接続

SSHサーバを立ち上げます。まず、管理者としてGit Bashを実行します。

image.png (217.8 kB)

GitをインストールしたフォルダにSSHキーを作っていきます。Gitインストール直後は以下のようなファイル構成になっているはずです。 C:Program Files\Git\etc\ssh

image.png (47.9 kB)

パスフレーズは入力せずにEnterを押して、SSHキーを作っていきます。

cd /c/'Program Files'/Git/etc/ssh
ssh-keygen -t rsa -f ssh_host_rsa_key
ssh-keygen -t ecdsa -f ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f ssh_host_ed25519_key

作成すると、Git/etc/sshフォルダ内は以下のようになります。

image.png (67.8 kB)

続いて、sshd.exeを実行して、SSHサーバを立ち上げます。

/usr/bin/sshd.exe

ファイアウォールの設定を聞かれるので、「アクセスを許可する」をクリックします。

image.png (51.5 kB)

タスクマネージャーで確認すると、sshd.exeが起動していることが確認できると思います。

image.png (64.6 kB)

最後に、クライアント側で用意した公開鍵id_rsaをサーバ側に登録しておきます。

C:/Users/ユーザ名/.sshフォルダの直下にauthorized_keysというファイルを作成します。
ファイルをテキストエディタなどで開き、クライアント側で用意した公開鍵の内容をコピペします。

image.png (52.6 kB)

4. 外部接続を行うGit Daemonの起動(SSH接続では必要ない)

Gitプロトコルで通信を行う場合は、以下のコマンドでGitサーバを立ち上げておく必要があります。

# git daemon --verbose --export-all --enable=receive-pack --base-path=/c/repos/
git daemon --verbose --reuseaddr --export-all --enable=receive-pack --enable=upload-pack --base-path=/c/repos/

デフォルトは読み取り専用になっています。つまり、git clonegit fetchgit pullはできるけど、git pushはできません。

--export-allをつけてリモートレポジトリにプッシュできるようにしておくように設定します。
また、--enable=receive-packをつけて、認証を受けていないanonymousユーザもプッシュできるようにします。

先ほどのコマンドを実行すると、ファイアウォールの確認画面が出てくるので、「アクセスを許可する」をクリックします。

image.png (54.4 kB)

クライアント側の設定

最後に、クライアント側でGitリポジトリのクローンの作成とGitリポジトリへのプッシュができるか確認します。

1. クローンの作成

ipconfigであらかじめIPアドレスを確認しておきます。
以下では、IPアドレス192.168.86.21、サーバ側のGitのリモートレポジトリがC:/repos/sample.gitだった場合の例を示しました。

コマンドプロンプトで以下のコマンドを実行しました。

git clone ssh://192.168.86.21/c/repos/sample.git

image.png (27.5 kB)

2. SourceTreeで管理する場合

コマンド操作でGitによるバージョン管理をしても良いですが、GUIを使うともっと便利です。今回はSourceTreeを使った例を示します。

まず、クライアント側で用意した秘密鍵id_rsaをSourceTreeに登録しておきます。[ツール] -> [オプション]からSSHキーを設定します。SSHクライアントにはOpenSSHを選択します。

image.png (62.9 kB)

3. SourceTreeでのGitリポジトリのクローン

SourceTree上でGitリポジトリのクローンを作成します。まず、新しいタブから「Clone」を選択し、クローンのURLを指定します。上記の例だと、ssh://192.168.86.21/c/repos/sample.gitになります。

image.png (97.3 kB)

「クローン」をクリックすると、対象のGitリポジトリのクローンを作成できます。

3. SourceTreeでコミットとプッシュを実行

GitリポジトリREADME.mdファイルを追加してコミットを行います。

image.png (136.4 kB)

続いて、プッシュを行います。プッシュをクリックすると、以下の画面が表示されるので、masterブランチを選択し、「プッシュ」をクリックします。

image.png (39.8 kB)

SSH接続がサーバ・クライアント間でできていれば、以下のようにプッシュが完了します。

image.png (156.2 kB)

トラブルシューティング

SourceTreeからのプッシュがいつまで立っても終わらない…

以下の設定を行うことで解決。

git config --global sendpack.sideband false

SourceTreeのPushが終わらない(社内ローカル +Windows環境)
https://teratail.com/questions/110660

Gitサーバに繋がらない…

Gitがクローンできない理由として、Windowsのユーザ認証が邪魔をしている可能性があります。
IPアドレスの前にログインユーザ名(サーバ側)、IPアドレスの後ろにSSHのポート番号を指定して実行するとうまくいきます。

git clone ssh://imama@192.168.86.31:22/c/repos/sample.git

参考

Windows Server上にGitリモートリポジトリを導入する手順書
https://qiita.com/nipoko/items/6e81a6021358ff8c03e9
WindowsのGitサーバ(リモートリポジトリ)構築メモ
http://nosource.blog35.fc2.com/blog-entry-142.html
gitで日本語ファイル名を表示する方法
https://qiita.com/kozo/items/08dc2b86ae3ba3f282c3
How to fix Windows 7 64 Bit git push msysgit hang up Problem
https://weberde.wordpress.com/2013/02/06/how-to-fix-windows-7-64-bit-git-push-msysgit-hang-up-problem/

Ubuntu 18.04 LTSにDockerを使ってGitLabとMattermostを導入してみた

はじめに

Gitのバージョン管理システムとしてGitHub継続的インテグレーションツールとしてCircleCIやTravisCI、開発者向けのコミュニケーションツールとしてSlackといったクラウドサービス(SaaS)が注目を集めています(というより、昨今では当たり前に使われているツールかも)。

しかし、会社によってはクラウドはNGでオンプレミスである必要があったり、予算的な問題があったりとなかなか導入できない事情があるかと思います。

オープンソースGitHubやCircleCI、Slack風の機能を実装したツールはないものか…。 そこで、GitLabの出番です!

about.gitlab.com

GitLabって何?

GitLabは、GitHub風なGitのバージョン管理ツールに加えて、システム開発のフロー全体をカバーする様々なツールを提供してくれます。コア機能についてはオープンソースで開発が行われており、フリーで自前のサーバに導入可能です(オープンソース版であるGitLab Community Edition (CE)はMIT License下で配布されています)。

GitLabの具体的な機能としては、Gitによるバージョン管理以外に、継続的インテグレーション・継続的デリバリー(GitLab CI/CD)、チケット管理ツール、各種コミュニケーションツール(Mattermost含む)、監視ツール(Prometheus)、Dockerイメージレジストリ(GitLab Container Registry)、Web IDEなどなど、たくさんの有用な機能を使うことができます(もちろん、フリーの範囲内で利用可能)。

上記のサービスに対応するSaaSGitHub、CircleCI、JIRAなど)を使う場合には、どうしても費用がかかってしまいますし、別々のサービスになるので管理も大変になります。GitLabならオールインワンで、それらのサービスがフリーで手に入ります(ただし、オンプレミスに限る。もちろん、サーバの管理も必要になる)。

機能の詳細については、公式のドキュメントを参照してみてください(Core / Freeとなっているのが、オープンソースで開発されているFree版で使える機能になります)。

about.gitlab.com

また、これらのサービスを活用することで、チケット駆動開発TiDD)、テスト駆動開発(TDD)、継続的インテグレーション・継続的デリバリー(CI/CD)などのモダンな開発手法を開発プロセスに組み込んでいくことができます。

最近、Ubuntu 18.04 LTS(デスクトップ版)をインストールしたPCを用意したので、今回はこの環境にGitLabを導入してみたいと思います。また、GitLabのDockerイメージからGitLabサーバを立ててみたいと思います(SlackクローンであるMattermostも同梱されているのでこれも導入してみます)。

なぜDockerを使うのか?

以下は、個人的な意見です。Dockerは使い始めたばかりなので、間違っている箇所もあるかもしれませんが、DockerコンテナとしてGitLabを導入するメリットを挙げてみました。

GitLabのすべての構成が1つのDockerイメージに集約されている (Monolithic Image)

GitLabのDockerイメージは、すべてのツールを単一のコンテナに収めたモノリシックなDockerイメージです。そのため、NginxやPostgreSQLなどのGitLabを構成するミドルウェアのDockerコンテナを別途立ち上げる必要はありません。やることとしては、GitLabのDockerイメージをpullした後、イメージを起動させるだけです(使用者から見ると構成がシンプル)。

インフラ構成がDockerfileとしてコード化されている (Infrastructure as Code)

DockerならOS固有のインストール手順に従う必要がありません(仮想環境で実行するため、OSの違いを吸収できる)。DockerfileとしてDockerイメージの構成がコード化されており、利用者はそのファイルを実行することでDockerイメージを自動で生成することができます。そのため、インストール手順書を見ながらGitLabを導入するなんてことも必要ありません(誰でも簡単にGitLabを立ち上げることができる)。

別環境への移行が簡単 (Portability)

Dockerはポータビリティ性に優れています。新しいサーバにGitLabのシステムを移行したい場合には、既存のGitLabの環境を簡単に新しい環境に移行することが可能です。異なるOSだから、インストール方法が変わってしまう、データの引き継ぎが面倒ということはありません。

以上の観点から、中長期的にGitLabを運用していくにあたり、ホストOSに直接GitLabをインストールするのではなく、DockerコンテナとしてGitLabを運用したほうがメリットが大きいと考えられます。

検証環境

  • Ubuntu 18.04 LTS (デスクトップ版)(サーバ側)
  • Windows10 Pro(クライアント側)

Dockerのインストール

以下のUbuntuへのDockerのインストール方法は、Dockerの公式ドキュメントを参考にしました。詳しくは、そちらを参照のこと。

Get Docker CE for Ubuntu
https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-repository

まず、aptパッケージのインデックスをアップデートします。

$ sudo apt-get update

HTTPS経由でリポジトリを使うようにするため、追加のパッケージをインストールします。

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

Docker公式のGPGキーを追加します。

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

GPGキー(9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88)を取得できたか確認します。

$ sudo apt-key fingerprint 0EBFCD88
pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [  不明  ] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

Stable版のDockerのリポジトリを設定します。 現状、Ubuntu17.10以前のバージョンでは以下の方法でOKです。

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

一方、Ubuntu18.04の場合、まだDockerがバージョンに対応できていないので、$(lsb_release -cs)の箇所(bionic)をartfulに書き換えて以下のように設定します。

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   artful \
   stable"
参考

https://linuxconfig.org/how-to-install-docker-on-ubuntu-18-04-bionic-beaver

もう一度、aptパッケージのインデックスをアップデートします。

$ sudo apt-get update

最新のStable版Dockerをインストールします。

$ sudo apt-get install docker-ce

特定のバージョンのDockerをインストールしたい場合、以下のコマンドで、インストール可能なDockerのバージョンを確認できます。

$ apt-cache madison docker-ce
 docker-ce | 18.03.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu artful/stable amd64 Packages
 docker-ce | 17.12.1~ce-0~ubuntu | https://download.docker.com/linux/ubuntu artful/stable amd64 Packages
 docker-ce | 17.12.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu artful/stable amd64 Packages

GitLabのDockerイメージの準備・起動

それでは、いよいよGitLabのDockerイメージの準備をしていきます。

詳しくは公式ドキュメントを参照してください。
https://docs.gitlab.com/omnibus/docker/

GitLab公式のDockerイメージはこちら。
https://hub.docker.com/r/gitlab/gitlab-ce/

まず、GitLabのDockerイメージをpullしてきます。

$ sudo docker pull gitlab/gitlab-ce

次に、GitLabのデータの永続化のために、GitLab用のファイルを保存するディレクトリをあらかじめつくっておきます(ディレクトリが存在しない場合、Docker起動後に自動的に生成されるようなので必要ないかも…)。

/home/imamachi/desktop/は適当なディレクトリを指定してください。以下は、設定例になります。

$ mkdir -p /home/imamachi/desktop/gitlab/config
$ mkdir -p /home/imamachi/desktop/gitlab/logs
$ mkdir -p /home/imamachi/desktop/gitlab/data

今回は、ローカルネットワーク経由でアクセスできるようにしたいので、Ubuntuのマシンに割り当てられているIPアドレスを調べておきます。

$ ifconfig

上記のコマンドをインストールしていない場合、以下のコマンドでインストールしておきましょう。

$ sudo apt install net-tools

GitLabのDockerイメージを起動するために、以下のコマンドを実行します。 以下のオプションは、自身の環境に合わせて設定します。
--hostname: Ubuntu(サーバ側)に割り当てられているIPアドレス
--volume: /home/imamachi/desktop/の部分は、先ほど作成したディレクトリのパスに合わせてください。
--name: 起動するコンテナの名称。任意の名前でOKですが、わかりやすくgitlabにしておきました。

sudo docker run --detach \
    --hostname 192.168.100.114 \
    --publish 443:443 --publish 80:80 --publish 22:22 --publish 8001:8001 \
    --name gitlab \
    --restart always \
    --volume /home/imamachi/desktop/gitlab/config:/etc/gitlab \
    --volume /home/imamachi/desktop/gitlab/logs:/var/log/gitlab \
    --volume /home/imamachi/desktop/gitlab/data:/var/opt/gitlab \
    gitlab/gitlab-ce:latest

--volumeの内容をまとめると、以下の通り。

ローカルディレクト コンテナ内ディレクト 内容
/home/imamachi/desktop/gitlab/config /etc/gitlab GitLabの設定ファイルを格納
/home/imamachi/desktop/gitlab/logs /var/log/gitlab GitLabのログファイルを格納
/home/imamachi/desktop/gitlab/data /var/opt/gitlab GitLabの各種データを格納

--publishでは、サービスごとのポート番号(ホストOS側 : Dockerコンテナ側)を指定しています。

サービス等 ポート番号
HTTPS 443
HTTP 80
SSH 22
Mattermost 8001

--restartalwaysを設定しておくと、ホストOSをリブート(再起動)したときに、自動的にGitLabのDockerイメージを起動させることができます。特別な理由がない限り、この設定でOKだと思います。

毎回、上記のコマンドをコピペして実行していたら面倒なので、Dockerのコマンド類をmakefileにまとめて置くと便利です。

以下は、GitLab用のmakefileの例です。

start:
  sudo docker run --detach \
      --hostname 192.168.100.114 \
      --publish 443:443 --publish 80:80 --publish 22:22 --publish 8001:8001  --publish 9090:9090 \
      --name gitlab \
      --restart always \
      --volume /home/imamachi/Desktop/gitlab/config:/etc/gitlab \
      --volume /home/imamachi/Desktop/gitlab/logs:/var/log/gitlab \
      --volume /home/imamachi/Desktop/gitlab/data:/var/opt/gitlab \
      gitlab/gitlab-ce:latest

restart:
  sudo docker restart gitlab

stop:
  sudo docker stop gitlab

rm:
  sudo docker rm gitlab

例えば、GitLabのDockerイメージの起動は以下のコマンドで実行可能になります。

$ make start

Ubuntuにmakeコマンドがインストールされていない場合、以下のコマンドでインストールしてください。

$ sudo apt install make

GitLabの起動が完了したかどうか確認するために、Dockerイメージの起動時に設定したGitLabのログファイルの出力先(上の例では、/home/imamachi/Desktop/gitlab/logs)を参照します。

logsディレクトリ直下のreconfigureディレクトリ内に*.logファイルが出力されるはずです。コンテナ起動中は、随時ログ情報が書き込まれていきます。

起動が正常に完了すると、最後に以下のログが出力されるはずです。

[2018-04-28T22:33:27+00:00] INFO: Running report handlers
[2018-04-28T22:33:27+00:00] INFO: Report handlers complete

GitLabにアクセスしてみる

http://<IPアドレス>から、GitLabにアクセスすることができます(上記の例では、http://192.168.100.114)。

初期画面では、rootユーザのパスワードの設定画面が表示されます。任意のパスワードを設定して、Change your passwordをクリックします。

Screenshot from 2018-04-19 07-31-27.png (46.9 kB)

次に、ログイン画面が表示されるので、rootユーザもしくは新規にユーザを作成(Register)してGitLabにログイン(Sign In)します。

Screenshot from 2018-04-19 07-31-51.png (43.7 kB)

初回ログインでは、以下のスタートメニューが表示されます。

image.png (123.7 kB)

SSHキーの設定

公開鍵認証によりGitLabとやり取りをするために、SSHキーの設定を行います。

Windows10の場合

WindowsではおなじみのPuTTY Keyだとうまく行かなかったので、OpenSSHにしました。

こちらのGitのサイトから、Git for Windowsをインストールしておきます。
https://git-scm.com/download/win

また、Git用のクライアントアプリとして、SourceTreeをインストールしておきます。
https://ja.atlassian.com/software/sourcetree

Git for Windowsのインストールが完了したら、Git Bashを起動します。

image.png (28.0 kB)

Git Bash上で、以下のコマンドから、SSHキーを生成します。

$ ssh-keygen -t rsa

すると、C:\Users\<ユーザ名>\.ssh以下にid_rsa.pubという名前の公開鍵が生成されるので、テキストエディタなどでファイルを開き、ファイルの中身をコピーします。

image.png (92.6 kB)

User SettingsのSSH Keysの画面から、先ほどコピーしたSSHキーをKey欄に貼り付けます(Titleも自動的につきます)。内容に問題がなければ、Add KeyをクリックしSSHキーを登録します。

image.png (81.6 kB)

SSH Keysを再度クリックして見ると、以下のようにSSHキーが登録されていることが確認できると思います。

image.png (54.6 kB)

今度は、SourceTreeを起動し、先ほど用意した秘密鍵の方を設定しておきます。 SourceTreeの[ツール] -> [オプション]をクリックします。

image.png (25.4 kB)

SSHクライアントの設定で、SSHキーに先ほど用意した秘密鍵をセットします。 SSHクライアントには、OpenSSHを設定します。

image.png (63.6 kB)

続いて、GitLab上のリモートレポジトリを取得します。 まず、GitLab上でリポジトリを作成し、赤枠で囲んだリポジトリのパスをクリップボードにコピーします。

image.png (183.9 kB)

SourceTreeのCloneタブから、先ほどコピーしたリポジトリのパスをペーストします。 「クローン」ボタンをクリックすると、ローカルにリモートリポジトリのクローンを作成できます。

image.png (98.3 kB)

Ubuntuの場合(MacOSの場合もほぼ同様)

以下のコマンドから、SSHキーを生成します。

$ ssh-keygen -t rsa

すると、~/.ssh以下にid_rsa.pubという名前の公開鍵が生成されるので、ファイルの中身をコピーします。

例えば、catコマンドでファイルの中身をコンソールに出力し、内容をコピーしていきます。

$ cat ~/.ssh/id_rsa.pub
(余談)クリップボードへのコピー

上記のように、手作業でコピーしているとミスを誘発する可能性があるので、できればやりたくないです。そこで、コマンド操作でクリップボードへコピーする方法を取ります。

xselコマンドは標準でUbuntuに入っていないので、以下のコマンドでインストールしておきます(何かと使うので入れておくと便利です)。

$ sudo apt install xsel

以下のように、クリップボードへファイルの中身をコピーすることが可能です。でも、xselのコマンドオプションが2つもあって面倒くさいです…。

$ cat ~/.ssh/id_rsa.pub | xsel --clipboard --input

なので、MacOSpbcopyと同じ名前のエイリアスをつけておきます(名前はわかりやすければ何でもいいです)。

$ echo "alias pbcopy='xsel --clipboard --input'" >> ~/.bashrc
$ source ~/.bashrc

すると、以下のコマンドでクリップボードにファイルの中身をコピーできるようになります。

$ cat ~/.ssh/id_rsa.pub | pbcopy

User SettingsのSSH Keysの画面から、先ほどコピーしたSSHキーをKey欄に貼り付けます(Titleも自動的につきます)。内容に問題がなければ、Add KeyをクリックしSSHキーを登録します。

image.png (81.6 kB)

SSH Keysを再度クリックして見ると、以下のようにSSHキーが登録されていることが確認できると思います。

image.png (54.6 kB)

以降の処理は、Windowsと同じなので割愛します。

参考

公開鍵暗号を用いてのSSH接続(きほん)
https://qiita.com/mukoya/items/f20def019e25dc162ca8
コマンドラインからクリップボードへのコピー
https://qiita.com/Kzno/items/6f2fa98256bdffb0fd43

MattermostへGitLabのアカウントでシングルサインオン(SSO)する

GitLabに同梱されているMattermostは、別途Mattermost用のアカウントを作成しなくても、GitLabのアカウントからログインすることができます(シングルサインオン(SSO))。

以下では、GitLabアカウントでのシングルサインオンを行うための設定について紹介します。

ブラウザからGitLabにアクセスし、rootユーザでログイン後、Settingsから、

Screenshot from 2018-04-19 07-33-41.png (18.4 kB)

Applicationsタブに移動し、Mattermostという名前のアプリケーションをGitLabに登録します。 Redirect URIには、以下のURIを指定します(IPアドレスにはホストOSに割り当てられている値を設定してください。ここでは、192.168.100.114にしています)。

http://192.168.100.114:8001/signup/gitlab/complete
http://192.168.100.114:8001/login/gitlab/complete

同じサーバで運用している場合、以下のようにMattermostのポート番号も指定する必要があります。そうしないと、リダイレクトに失敗してしまうので注意です。

Screenshot from 2018-04-19 07-34-47.png (101.4 kB)

Save applicationボタンをクリックし、登録を完了してください。登録に成功すると、以下の画面が表示されます。ここで、Application idSecretの値を次に使うので、控えておいてください。

image.png (85.8 kB)

詳しくは以下を参考のこと。
https://docs.gitlab.com/omnibus/gitlab-mattermost/

続いて、GitLabの設定ファイルを変更します。 まず、一時的にgitlab.rbを編集可能にしておきます(もしくはVimで編集)。

$ cd /home/imamachi/desktop/gitlab/config/
$ sudo chmod 755 gitlab.rb

1125行目辺りにある、以下を編集します。 http://<IPアドレス>:8001と設定します。

mattermost_external_url 'http://192.168.100.114:8001'

Screenshot from 2018-04-19 07-37-17.png (35.5 kB)

1219-1225行辺りにある、以下をコメントアウトをはずして内容を編集します。
gitlab_enable: trueに変更。
gitlab_id: 先ほどのApplication idを指定。
gitlab_secret: 先ほどのSecretを指定。
gitlab_auth_endpoint: http://<IPアドレス>/oauth/authorizeを指定。
gitlab_token_endpoint: http://<IPアドレス>/oauth/tokenを指定。
gitlab_user_api_endpoint: http://<IPアドレス>/api/v4/userを指定。

mattermost['gitlab_enable'] = true
mattermost['gitlab_id'] = "abfb91bd4ebd564d515be4f3d34cb3feb23eeb30a1d47b21548e3f9a63d2b502"
mattermost['gitlab_secret'] = "1e60f2d1148c712a69a3771ccf095db8dd812f482e98360c3b7e0330f168eae7"
mattermost['gitlab_scope'] = ""
mattermost['gitlab_auth_endpoint'] = "http://192.168.100.114/oauth/authorize"
mattermost['gitlab_token_endpoint'] = "http://192.168.100.114/oauth/token"
mattermost['gitlab_user_api_endpoint'] = "http://192.168.100.114/api/v4/user"

Screenshot from 2018-04-20 07-54-05.png (38.8 kB)

GitLabのDockerコンテナを一旦停止させて、破棄します。

$ sudo docker stop gitlab
$ sudo docker rm gitlab

makefileを用意していれば、以下のコマンドで実行できます。

$ make stop
$ make rm

続いて、Dockerコンテナを起動します。

$ sudo docker run --detach \
    --hostname 192.168.100.114 \
    --publish 443:443 --publish 80:80 --publish 22:22 --publish 8001:8001 \
    --name gitlab \
    --restart always \
    --volume /home/imamachi/desktop/gitlab/config:/etc/gitlab \
    --volume /home/imamachi/desktop/gitlab/logs:/var/log/gitlab \
    --volume /home/imamachi/desktop/gitlab/data:/var/opt/gitlab \
    gitlab/gitlab-ce:latest

makefileを用意していれば、以下のコマンドで実行できます。

$ make start

参考

https://docs.gitlab.com/omnibus/docker/
https://docs.gitlab.com/omnibus/gitlab-mattermost/

GitLabのDockerコンテナを起動した後、http://<IPアドレス>:8001/にアクセスします(ここまでの例では、http://192.168.100.114:8001/)。すると、GitLab Mattermostのログイン画面が表示されます。

Screenshot from 2018-04-19 07-48-49.png (27.7 kB)

リダイレクトが正しく設定されていると、GitLab Single Sign-Onをクリックした後、以下の画面が表示されます。

image.png (85.4 kB)

Authorizeボタンをクリックすると、Mattermostにログインできます。Create a new teamをクリックし、

Screenshot from 2018-04-19 07-53-09.png (29.7 kB)

チーム名を入力して登録すると、

Screenshot from 2018-04-19 07-53-25.png (28.0 kB)

Screenshot from 2018-04-19 07-53-32.png (37.9 kB)

Mattermostのメイン画面が表示されるはずです。

Screenshot from 2018-04-19 07-53-44.png (60.4 kB)

基本的な準備は、以上で完了です。

まとめ

  • GitLabのDockerイメージの準備・起動
  • GitLabへのSSHキーの設定
  • Mattermostの起動(GitLabアカウントによるSSO)

今回、上記の3つについて、やり方をまとめてみました。他にも、重要なこととしてバックアップのとり方や、サーバ監視などがありますが、今回は割愛しました。以下に、公式のドキュメントのリンクを示すのにとどめておきます。

Backing up and restoring GitLab
https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-installations
GitLab Prometheus
https://docs.gitlab.com/ee/administration/monitoring/prometheus/

Windows10もしくはMacOSからUbuntu 18.04 LTSにリモート接続(リモートデスクトップ)してみた

Ubuntu 18.04 LTS(デスクトップ版)にWindowsもしくはMacOSからアクセス方法(いわゆる、リモートデスクトップのやり方)の紹介です。ネットで調べてみるといろいろな情報が散見されており、個人的にわかりにくかったのでやり方をまとめてみました。

以下では、VNCによるWindowsもしくはMacOSからUbuntu 18.04 LTS(デスクトップ版)へのリモート接続方法を示しました。ちなみに、サーバ版のUbuntuではやり方が異なるので注意してください。

使用したOS

注意事項

Ubuntu17.10で初めて採用されたディスプレイサーバの「WayLand」では、現在、以下の方法でリモート接続できません(Ubuntu18.04 LTSではデフォルトで「Xorg」が採用されているので大丈夫です)。

1. Ubuntu18.04 LTS側での設定

以下では、Ubnutu18.04における設定方法を示しました。 まず、設定から「共有」をオンにし、画面共有をアクティブにします。

image.png (63.5 kB)

以下の詳細設定では、「このスクリーンの操作する接続を許可する」にチェック、アクセスオプションの「パスワードを要求する」にチェックをつけます。

このとき、「新規接続の場合アクセス要求を必要とする」にチェックすると、Ubuntu側で接続要求を許可するかどうか毎回確認が入るので、パスワードの要求のほうが便利です。

image.png (72.7 kB)

さらに、Windowsからリモート接続する場合、通信の暗号化処理をオフにしておく必要があります(通信内容が暗号化されなくなるので、セキュリティ的に問題があります。リモート接続はローカルネットワークなどの限定された範囲で行ったほうが良さそうです)。

$ sudo gsettings set org.gnome.Vino require-encryption false

また、すでにファイアウォールの設定がされているかどうか確認します。

$ sudo ufw status
状態:非アクティブ

となっていれば、ファイアウォールが有効になっていないのでリモート接続できる状態にあります。

ファイアウォールが有効になっている場合、以下のように5900番ポートを許可する設定を行います。

$ sudo ufw allow 5900
$ sudo ufw reload
$ sudo ufw status

qiita.com

2. Windows10の設定

好きなVNC Viewerを使って、Ubuntuにリモート接続します。Windowsにデフォルトで入っているリモートデスクトップアプリは通信プロトコルが異なるため利用できません。

ここでは、TightVNCを使いました。オープンソースで開発されており、フリーで利用可能です。いくつかのViewerを使ってみたところ、TightVNCが最も軽快に動作する印象でした。

以下のサイトからダウンロードします。
www.tightvnc.com

image.png (314.3 kB)

インストールするといろいろなアプリが入ってきますが、Viewerである「TightVNC Viewer」をクリックして起動します。

202018-04-28%2019.52.38.png (40.4 kB)

「Remote Host」にローカルネットワーク上のIPアドレス(Ubnutu側)を入力し、ポート番号を「5900」に設定します。

image.png (105.4 kB)

Ubuntu側のPCに割り当てられているIPアドレスがわからない場合は、以下のコマンドで調べることができます。

$ ifconfig

接続に問題がなければ、Ubnutu側で設定したパスワードを入力する画面が出てきます。

image.png (21.4 kB)

パスワードを入力した後、OKボタンをクリックするとUbuntu側のPCにリモート接続できるはずです。

image.png (704.9 kB)

3. MacOSの設定

次に、MacOSからUbuntu側へのリモート接続を試したいと思います。

まず、Finderの「移動」から「サーバへ接続」をクリックします。

image.png (1.1 MB)

サーバアドレスにローカルネットワークのIPアドレスUbuntu側のもの)とポート番号を入力します。

image.png (78.9 kB)

この時、「+」ボタンをクリックし、設定を保存しておくと次回以降の接続が簡単になります。

image.png (88.6 kB)

接続に問題がなければ、Ubuntu側で設定したパスワードを入力する画面が出てきます。

image.png (74.2 kB)

パスワードを入力した後、OKボタンをクリックするとUbuntu側のPCにリモート接続できるはずです。

image.png (4.2 MB)

4. おまけ

4月26日にリリースされたUbuntu 18.04 LTSをインストールしたらとりあえずやっておきたいことをまとめました。

とりあえずアップデート

インターネットに接続していれば、自動でアップデートがかかるので更新しておく。 続いて、以下のコマンドでアップデートをかける。

$ sudo apt update
$ sudo apt upgrade

ifconfigとmakeコマンドを使えるようにする

$ sudo apt install net-tools
$ sudo apt install make

日本語名のディレクトリを英語表記に変更する

フォルダ名が日本語なのは使いにくいので、以下で一括で英語表記に設定。 ウインドウが表示されるので、「Update Names」をクリックしディレクトリ名を変更する。

$ LANG=C xdg-user-dirs-gtk-update

image.png (75.6 kB)

変更されると、以下のようになる。

image.png (88.8 kB)

もしくは、すでに自力でディレクトリ名を変更してしまった場合は、以下の方法で新しいディレクトリ名とデスクトップやドキュメントなどのリンクを対応付けする。

cd ~/.config
sudo chmod 755 user-dirs.dirs
code user-dirs.dirs

VSCodeで編集。

# This file is written by xdg-user-dirs-update
# If you want to change or add directories, just edit the line you're
# interested in. All local changes will be retained on the next run
# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
# absolute path. No other format is supported.
# 
XDG_DESKTOP_DIR="$HOME/desktop"
XDG_DOWNLOAD_DIR="$HOME/download"
XDG_TEMPLATES_DIR="$HOME/templates"
XDG_PUBLICSHARE_DIR="$HOME/share"
XDG_DOCUMENTS_DIR="$HOME/document"
XDG_MUSIC_DIR="$HOME/music"
XDG_PICTURES_DIR="$HOME/picture"
XDG_VIDEOS_DIR="$HOME/video"
chmod 600  user-dirs.dirs

日付表示

$ gsettings set org.gnome.desktop.interface clock-show-date true

image.png (5.2 kB)

参考

Ubuntu 17.10のインストール直後にやっておきたいことまとめ
https://linuxfan.info/ubuntu-17-10-basic-settings https://qiita.com/scapegoat_11_/items/3ff95addfabef8f9d10d

Dockerコンテナ上でNGSのソフトウェアを実行してみる(Windows10・MacOSXローカル環境編)

きっかけ

近年では、BiocondaのようなBiology関連ソフトウェアに対するパッケージマネージャが登場し、NGS関連のソフトウェアのインストールがグッと簡単になりました(Biocondaが登場する前は、いちいちソースコードからコンパイルする必要があったり、各ソフトウェア固有のインストール方法を理解する必要があったり、とにかく手間がかかっていました…。NGS関連のソフトは依存関係が複雑で本当にやっかい)。

ただ、いろんな人のNGS関連のブログを見ていると、環境によってはBiocondaでうまくインストールできないという事例もあるようです(Biocondaレシピで想定されていなかったパッケージへの依存によるもの?)。確かに、Biocondaは非常に便利なんですが、他の環境でも同じ解析環境を構築しようとすると、再現よく環境を構築できないケースがあることがわかってきました。

そこで、ソフトウェアごとに仮想環境を構築し、各ソフトウェアの動作が保証された環境を色々な解析に使いまわすことで、上記の問題を解決しようと考えました。

そこで、Dockerの出番です。Dockerはコンテナ型仮想化技術の1つであり、ホストOS上で単一のプロセスとして起動します。ホストOSと同じカーネルを共有するため、VMWare, VirtualBoxなどのホスト型仮想化技術と比較して、軽量であるとされています。

「Docker」を全く知らない人のために「Docker」の魅力を伝えるための「Docker」入門
https://qiita.com/bremen/items/4604f530fe25786240db

前置きが長くなりましたが、今回は、Dockerを土台としたシステム基盤をつくることを考えるために、まずはローカル環境でDockerコンテナを動かしてみた (FastQCを実行して見る)という内容になります。

Dockerをベースにした解析パイプラインの活用事例

パッと目についた事例をあげてみました。他にもたくさんあると思います。

High-Throughput Genomics on AWS - LFS309 - re:Invent 2017

AWSのカンファレンス re:Invent 2017で紹介されたNGS解析のパイプライン
https://www.slideshare.net/AmazonWebServices/highthroughput-genomics-on-aws-lfs309-reinvent-2017

Broad Institute: Genomes-in-the-cloud

Broad Instituteで利用されているゲノム解析用のパイプライン
https://hub.docker.com/r/broadinstitute/genomes-in-the-cloud/

BioContainers

バイオインフォマティクス関連のDockerイメージファイルをまとめたもの
https://biocontainers.pro/

ベースとなるDockerイメージの選択

NGSのデータ解析をする上では、必要最小限のLinuxディストリビューションのDockerイメージを使用した方がいいと思います。1つはイメージサイズが小さいほど、Dockerイメージの起動や破棄、ダウンロードなどの取り回しの面で有利だから。もう1つは、軽量コンテナの方が不要なパッケージが少なく、セキュリティ上、潜在的な攻撃を受けにくいからです。

また、ベースイメージを選定する上で、OSにインストールマネージャーがついているかどうかや、ITベンダーなどにより定期的にメンテナンスされているかどうかもポイントになります。

以下では、主要なLinuxディストリビューションについて簡単に比較をして見たいと思います。

Dockerイメージのサイズ

以下が主要なLinuxディストリビューションのDockerイメージのサイズになります。

Linux OS Compressed size
debian8.10-slim 30 MB
debian 8.10 53 MB
ubuntu 18.04 35 MB
centos 7.4.1708 73 MB

上記のデータは、2018-03-13時点のデータです。少し前までは、Debianが軽量なDockerイメージだったので、Debian一択なのかと思っていましたが、Ubuntuも直近ではかなりスリム化を果たしていますね(ちなみに、Anacondaやその他NGS関連のDockerイメージはDebianをベースに作られたものが多い気がします)。

脆弱性レポート

各Dockerイメージのレポジトリのtagタブから、各バージョンの脆弱性レポートを確認することができます。

image.png (328.0 kB)

スキャンされた各イメージをクリックすると、詳細を見ることができます。以下では、各LinuxディストリビューションのDockerイメージの脆弱性レポートを見ていくことにします。

debian8.10-slim

image.png (281.9 kB)

debian 8.10

image.png (283.9 kB)

ubuntu

image.png (281.8 kB)

centos 7.4.1708

image.png (308.9 kB)

脆弱性レポートまとめ

上記で示した脆弱性レポートの結果をまとめて見ました。いくつのコンポーネント脆弱性を抱えているかカウントした表が以下の通りになります。

Linux OS Vulnerability (Components)
debian8.10-slim 6
debian 8.10 6
ubuntu 18.04 0
centos 7.4.1708 16

上記のデータは、2018-03-13時点のデータです。Ubuntu脆弱性が0なのが際立っている気がします(本当かなって結果になりました)。

現状では、Debian-slimかUbuntuを選択するのが良いのかなと思いました。

Dockerのインストール

自身のパソコンにDockerをインストールします。 以下のURLから、Docker (Community Edition)をダウンロードできます。
https://www.docker.com/community-edition#/download

MacOSXにDockerをインストールして使う場合は以上でインストール完了です。
Windows10環境の場合、既存のコマンドプロンプトPowershellがどうも使いにくい(個人的な感想ですが)ので、Windows Subsystem for Linux (WSL)を導入して、BashシェルからDockerを扱えるようにしたいと思います。

Windows Subsystem for Linux (WSL)経由でホストOS (Windows10)のDockerを動かす

1. WSLをインストールする

注意: Dockerを使用するにはHyper-Vを利用する必要があるため、OSがWindows10 Proであることが必須です。

Miscrosoft storeからWSLをダウンロード・インストールできるようになったので、ストアからインストールしましょう。今回はUbuntuを導入しました。

image.png (22.4 kB)

WSLを使用するためには、「プログラムと機能」から「Windowsの機能の有効化または無効化」を開き、Windows Subsystem for Linuxにチェックをつけます。

image.png (73.0 kB)

2. DockerをWSLにインストールする

以下のUbuntuへのDockerのインストール方法は、Dockerの公式ドキュメントを参考にしました。詳しくは、そちらを参照のこと。

Get Docker CE for Ubuntu
https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-repository

WSLのBash shellを起動し、まずaptパッケージをアップグレードしておきます。

$ sudo apt-get update

次のDockerを動かすために必要な各種パッケージをインストールします。

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

Dockerの公式のGPGキーを加え、キー情報の確認を行っています。

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

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <docker@docker.com>
sub   4096R/F273FCD8 2017-02-22

Dockerをインストールします。

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

3. WSL側とホストOS (Windows10)側のDockerを連携させる

Docker for Windowsのデーモンに接続するための設定を行います。今の状態では、あくまでホストOS側(Windows10)とWSL側で別々にDockerをインストールしただけなので、WSL側から、ホストOS側のDockerのデーモンプロセスを操作できるのように連携させる必要があります。

以下のように、WSL側のDockerクライアントからホストOS側のデーモンを見れるように、環境変数DOCKER_HOSTを設定します。

$ echo "export DOCKER_HOST='tcp://0.0.0.0:2375'" >> ~/.bashrc
$ source ~/.bashrc

最後に、Windows10側のDockerの設定画面を開き、Expose daemon on tcp://localhost:2375 without TLSにチェックを付けます。これで、WSL側からホストOS側のDockerのデーモンを操作できるようになりました。

image.png (142.5 kB)

参照

Docker for Windowsで快適な環境を得るまでの そこそこ長い闘い
https://qiita.com/YukiMiyatake/items/73c7d6c4f2c9739ebe60
WSL(Bash on Windows)でDockerを使用する
https://qiita.com/yoichiwo7/items/0b2aaa3a8c26ce8e87fe
Docker for WindowsをWSLから使う時のVolumeの扱い方
https://qiita.com/gentaro/items/7dec88e663f59b472de6

VSCodeの総合ターミナルでWSLを使う

VSCodeでは、エディタ内でターミナルを開くことができるので、こちらの標準のターミナルをWSLに変更しておくと便利です。

まず。設定画面から、terminal.integrated.shell.windowsで検索します。

対象の設定に対して "terminal.integrated.shell.windows": "C:\\Windows\\System32\\bash.exe"のようにWSLのBash.exeのパスを指定します。

image.png (111.0 kB)

総合ターミナルを開いて確認すると、めでたくBashシェルが使えるようになっているはずです!

image.png (30.8 kB)

Dockerファイルの作成

まず、Linux OSのDockerイメージをベースイメージにして、その上にNGS解析のソフトウェアをインストールしたDockerイメージを作成します。

1. Debian9-slimにBiocondaをインストールしたDockerイメージを作成する

Linux OSのDebina9-slimをベースイメージにして、BiocondaをインストールしたDockerイメージを作成します。

以下のDockerfileは、condaの公式Dockerfileを参考しました。
https://hub.docker.com/r/conda/miniconda2/~/dockerfile/

&&で処理を連続して行っているのは、レイヤーを減らすためです。また、中間ファイルを削除することでDockerのイメージファイルのサイズを小さくしています。

Dockerfile

# Base image
FROM debian:9-slim

# Install Miniconda2 & Bioconda
RUN apt-get -qq update && apt-get -qq -y install curl bzip2 \
  && curl -sSL https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -o /tmp/miniconda.sh \
  && bash /tmp/miniconda.sh -bfp /usr/local \
  && rm -rf /tmp/miniconda.sh \
  && conda install -y python=2 \
  && conda update conda \
  && conda config --add channels r \
  && conda config --add channels defaults \
  && conda config --add channels conda-forge \
  && conda config --add channels bioconda \
  && apt-get -qq -y remove curl bzip2 \
  && apt-get -qq -y autoremove \
  && apt-get autoclean \
  && rm -rf /var/lib/apt/lists/* /var/log/dpkg.log \
  && conda clean --all --yes

ENV PATH /opt/conda/bin:$PATH

次に、DockerfileからDockerイメージを作成します。

$ docker build -t debian9-slim-bioconda2:latest -f Dockerfile .

2. FastQCをインストールしたDockerイメージを作成する

先程作ったDockerイメージをベースにして、FastQCのインストールしたイメージファイルを作成します。

Dockerfile

# Base image
FROM debian9-slim-bioconda2:latest

# Application entry point
# Dejavu fonts are not included with default::openjdk(fastqc recipe).
# They are already included with conda-forge::openjdk.
# https://github.com/conda-forge/staged-recipes/issues/3164 
RUN conda update conda \
  && conda install fastqc=0.11.6 \
  && conda install -c conda-forge openjdk \
  && conda clean --all --yes
COPY ./fastqc/run_fastqc_local.py /run_fastqc_local.py

ENTRYPOINT ["python", "/run_fastqc_local.py"]

Pythonのコードをエントリポイントに設定します。以下が、そのソースコードになります。

from __future__ import print_function

import os
import shlex
import subprocess
from argparse import ArgumentParser


def run_fastqc(fastq_path, cmd_args, working_dir):
    """
    Runs fastqc  
   :param fastq_path: Local path to fastq file  
   :param cmd_args: Additional command-line arguments to pass in  
   :param working_dir: Working directory  
   :return: Path to the result folder
    """
    # Prepare fastqc result path
    fastqc_result_dir = os.path.join(working_dir, '')

    # Prepare fastqc log path
    fastqc_log_path = os.path.join(fastqc_result_dir, "log_fastqc.txt")

    # Prepare fastqc command
    cmd = "fastqc -o {0} {1} {2}".format(
        fastqc_result_dir, cmd_args, fastq_path)
    print(cmd)

    # Execute fastqc
    with open(fastqc_log_path, 'w') as log_file:
        subprocess.check_call(shlex.split(cmd), stdout=log_file)

    return fastqc_result_dir


def main():
    argparser = ArgumentParser()

    argparser.add_argument('--fastq_path', type=str,
                           help="fastq sequence file", required=True)
    argparser.add_argument('--cmd_args', type=str,
                           help="arguments/options for fastqc", default="")
    argparser.add_argument('--working_dir', type=str, default="data/")

    args = argparser.parse_args()

    print("Creating working directory...")
    if not os.path.exists(args.working_dir):
        os.mkdir(args.working_dir)

    print("Running fastqc...")
    local_result_dir = run_fastqc(
        args.fastq_path, args.cmd_args, args.working_dir)

    print('Save the result in {0}.'.format(local_result_dir))

    print("successfully Completed !!")


if __name__ == '__main__':
    main()

次に、DockerfileからDockerイメージを作成します。Pythonのコードも同じディレクトリに置いておきます。

$ docker build -t debian9-slim-bioconda2-fastqc:latest -f Dockerfile .

以下のコマンドで作成したDockerイメージをチェックできます。

$ docker images

image.png (53.4 kB)

Dockerイメージの実行

1. FASTQファイルの準備

適当なFASTQファイルを持っていない場合、以下の記事を参考にしてテストに使うFASTQファイルを用意してください。

imamachi-n.hatenablog.com

2. Dockerコンテナを起動する

FASTQ_FILEにFASTQファイル、FASTQファイルが置いてあるLOCAL_WORKING_DIRに作業ディレクトリを指定します。また、DOCKER_IMAGEに先ほど作成したDockerイメージを、DOCKER_WORKING_DIRにDockerコンテナ内の適当な作業ディレクトリを指定します。

#!/bin/bash
#LOCAL_WORKING_DIR="/Users/imamachinaoto/Desktop/NGS/data" # MacOS
LOCAL_WORKING_DIR="/c/Users/imama/Desktop/NGS/fastqc/data"    # Windows10(WSL)
DOCKER_WORKING_DIR="/data"
DOCKER_IMAGE="debian9-slim-bioconda2-fastqc:latest"
FASTQ_FILE="RefSeq_hg38_2015-08-19_NM_ultraSlim.fq"

docker run --rm -it \
-v ${LOCAL_WORKING_DIR}:${DOCKER_WORKING_DIR} \
${DOCKER_IMAGE} \
--fastq_path ${DOCKER_WORKING_DIR}/${FASTQ_FILE} \
--working_dir ${DOCKER_WORKING_DIR}

ちなみに、DockerでWSL環境からホストOS(Windows10)のフォルダを見るとき、Cドライブは/mnt/cではなく、/cです。Bashシェルからアクセスするときは、/mnt/c(WSLにマウントされているCドライブを見る形)なのでパスの違いに注意が必要です。Windowsだと、これで詰まりました…。

コンテナでデータを管理する
http://docs.docker.jp/engine/userguide/dockervolumes.html

上記シェルスクリプト(もしくは以下で説明するmakeコマンド)を実行することで、FastQCが実行されます。

image.png (191.3 kB)

ホストOSのディレクトリを、Docker上のディレクトリに紐づけておくこと(ボリュームのマウント)で、以下のようにDockerコンテナが破棄されたあとでも、データを永続化させることができます。

image.png (36.4 kB)

Dockerコマンドをまとめたmakefileの作成

Dockerコマンドはイメージファイルの作成やコンテナ起動時など、繰り返し使用します。なので、今回はmakefileにコマンド類をまとめて、make buildmake startなどを用意することで、コマンド操作が簡単になります。

Windows10やWSLには、makeコマンドがインストールされていないため、あらかじめインストールしておきます。

Windows10でmakeファイルを実行する

WSLを使わない場合のmakeコマンドのインストール方法を示します。Windows10にはコマンドプロンプトからmakeコマンドを使えないので、まずmakeコマンドをインストールします。

1. makeコマンドをコマンドプロンプトに導入する(参考)

以下のURLから、makeをダウンロードします。
http://gnuwin32.sourceforge.net/packages/make.htm

image.png (225.1 kB)

C:\Program Files (x86)\GnuWin32\binにmake.exeが保存されているので、パスを通します。

image.png (56.5 kB)

2. WSL環境にmakeコマンドを導入する

WSLのコンソールから、以下のコマンドを実行するだけです。

$ sudo apt-get install make

Windowsでmakeコマンドを使う
https://qiita.com/tokikaze0604/items/e13c04192762f8d4ec85

makefileの例

NAME=debian9-slim-bioconda2-fastqc
TAG=0.11.6.local
UNDERSCORE_TAG=0_11_6_local

LOCAL_WORKING_DIR=/c/dev/NGS/fastqc/data
DOCKER_WORKING_DIR=/data
DOCKER_IMAGE="fastqc-aws-debian9-slim-bioconda2:0.11.6.local"
FASTQ_FILE=RefSeq_hg38_2015-08-19_NM_ultraSlim.fq

all: build push

build:
      docker build -t $(NAME):$(TAG) -t $(NAME):latest -f Dockerfile .
build-no-cache:
      docker build --no-cache -t $(NAME):$(TAG) -t $(NAME):latest -f Dockerfile .

push:
      docker push $(NAME):$(TAG)
      docker push $(NAME):latest

start:
      docker run --rm -it -v ${LOCAL_WORKING_DIR}:${DOCKER_WORKING_DIR} ${DOCKER_IMAGE} --fastq_path ${DOCKER_WORKING_DIR}/${FASTQ_FILE} --working_dir ${DOCKER_WORKING_DIR}

rm:
      docker rm `docker ps -aq`

rmi:
      docker rmi $(NAME):$(TAG) $(NAME):latest

つまづいたポイント

makefileの作成

インデントはスペースではなく、タブにしないとエラーになる。 Visual Studio Codeの場合、makefileと認識されたファイルでは、インデントをタブにするように設定されている。しかし、ファイル名がMakefileだと下記の設定が適応されない。makefileと小文字のmにする必要がある。

image.png (76.5 kB)

Docker関連の参考

docker コマンド チートシート
https://qiita.com/voluntas/items/68c1fd04dd3d507d4083
dockerでなrepositoryを消す
https://qiita.com/lirispp/items/06fc74c5bbc64fddf9ab

ART: シミュレーション用のRNA-seqデータを作成する

テスト用のFASTQファイルの作成

ART (a next-generation sequencing read simulator)を用いて、テスト用のFASTQファイルを作成します。

ARTのインストール

※ Biocondaをインストールしていることを前提にしています。
ARTをインストールします。

$ conda intall art

ARTが正しくインストールされたか確認します。

$ art_illumina --help

RefseqのGTFファイルをダウンロード

ARTを使ってテスト用のFASTQファイルを作るのですが、今回はRNA-seqのデータを作ろうと思います。

そこで、元となる配列を用意したいと思います。 TranscriptomeのデータをGTFファイルと取得し、それをFASTQのファイルに変換したいと思います。

GencodeのGTFファイルでもいいですが、ここでは必要なTranscriptomeデータが含まれておりコンパクトなRefseqのデータを使います。

illuminaのiGenomeサイトから、hg38のデータを丸ごとダウンロードします。この中に、RefSeqのGTFファイルも含まれています。

image.png (182.7 kB)

ダウンロードしたら、解凍します。

$ tar zxvf Home_sapiens_UCSC_hg38.tar.gz

解凍が終わったら、Homo_sapiensというディレクトリができるはずです。 Homo_sapiens/UCSC/hg38/Annotation/Archives/archive-2015-08-14-08-18-15/Genes/にあるgenes.gtfというファイルがRefSeqのGTFファイルになります(ちょっと古いデータですが、実際の解析に用いるわけではないので、良しとしましょう)。

これだけ適当なディレクトリに移動もしくはコピーしておき、それ以外のファイルは削除します。

このままだと、何のファイルかわからないのでリネームしておきます。

$ mv genes.gtf RefSeq_hg38_2015-08-19.gtf

GTFファイルからBEDファイルを作成

以下のスクリプトを使って、GTFファイルをBEDファイルに変換する。 gtf2bed.pl (3.8 kB)

$ perl gtf2bed.pl RefSeq_hg38_2015-08-19.gtf > RefSeq_hg38_2015-08-19.bed

このままだと、データが大きすぎるのでmRNAに限定し、かつRepresentative transcriptsをできるだけ抽出するようにします。
ExtractMrna.py (360 B)

$ python ExtractMrna.py RefSeq_hg38_2015-08-19.bed RefSeq_hg38_2015-08-19_NM_slim.bed

ヒトゲノム配列をダウンロード

image.png (1.5 MB)

image.png (1.5 MB)

image.png (300.8 kB)

image.png (71.1 kB)

image.png (273.5 kB)

$ wget http://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.fa.gz
$ gunzip hg38.fa.gz

BEDファイルからFASTAファイルを作成

BEDファイルからFASTA ファイルへ変換するために、Bedtoolsを使います。 まず、Bioconda経由でBedtoolsをインストールします。

$ conda install bedtools

BEDファイルをFASTAファイルに変換します。 ここで、先ほどダウンロードしたhg38.faファイルを使います。

$ bedtools getfasta -name -s -split -fi hg38.fa -bed RefSeq_hg38_2015-08-19_NM_slim.bed > RefSeq_hg38_2015-08-19_NM_slim.fa

-name: BEDファイルのname列の値を各配列の名称とする。
-s: ゲノム上での向き (Strandness)を考慮する(Transcriptomeなのでもちろん考慮します)。
-split: 12BED (12列のデータがあるBEDふぁいる)がInputである場合に指定 。
-fi: Referenceになる配列(ゲノム配列)のFASTAファイルを指定。
-bed: TranscriptomeのBEDファイルを指定。

このコマンドの実行には、FASTAファイルのインデックスファイルが必要になりますが、ファイルがない場合、自動的に生成してくれるので問題ないです。

> index file hg38.fa.fai not found, generating...

生成されたTranscriptomeのFATSAファイルは、標準出力で出力されます。

TranscriptomeのFASTAファイルからFASTQファイルを生成

今回は、illuminaのFASTQシーケンスデータ (RNA-seq, single-end)を生成したいと思います。ここでは、HiSeq2000のデータを作ります。

$ art_illumina -ss HS20 -i RefSeq_hg38_2015-08-19_NM_slim.fa -o RefSeq_hg38_2015-08-19_NM_slim -l 36 -f 2 --noALN
$ art_illumina -ss HS20 -i RefSeq_hg38_2015-08-19_NM_slim.fa -o RefSeq_hg38_2015-08-19_NM_slim_paired -l 36 -f 1 -p -m 300 -s 10 --noALN

-i --in: fasta形式の入力ファイルの指定。
-o --out: fastq形式の出力ファイルの指定 (拡張子はつけなくて良い)。
-ss --seqSys: シーケンサーの種類を選択。
指定する引数(System ID) - シーケンサー名 (リード長)

  • GA1 - GenomeAnalyzer I (36bp,44bp),
  • GA2 - GenomeAnalyzer II (50bp, 75bp)
  • HS10 - HiSeq 1000 (100bp)
  • HS20 - HiSeq 2000 (100bp)
  • HS25 - HiSeq 2500 (125bp, 150bp)
  • HS10 - HiSeq 1000 (100bp)
  • HS20 - HiSeq 2000 (100bp)
  • HS25 - HiSeq 2500 (125bp, 150bp)
  • HSXn - HiSeqX PCR free (150bp)
  • HSXt - HiSeqX TruSeq (150bp)
  • MinS - MiniSeq TruSeq (50bp)
  • MSv1 - MiSeq v1 (250bp)
  • MSv3 - MiSeq v3 (250bp)
  • NS50 - NextSeq500 v2 (75bp)

-l --len: リード長の指定。
-f --fcov: リードカバレージの指定。
-p --paired: Paired-endのデータとして出力(指定しない場合、Single-endのデータとして出力)。
m --mflen: フラグメントの平均サイズの指定(Paired-endのときのみ)。
-s --sdev: フラグメントのサイズの標準偏差の指定(Paired-endのときのみ)。
-sam --samout: SAMファイルを出力。
-na --noALN: アライメントファイル (ALN)を出力しない。
別にリード長は、指定された長さよりも短くても大丈夫です。

もっとファイルサイズを小さくしたい場合は、以下のように特定の行を抽出したファイルを作成します。

$ sed -n 1,200000p RefSeq_hg38_2015-08-19_NM_slim.fq > RefSeq_hg38_2015-08-19_NM_ultraSlim.fq

Seleniumコトハジメ - PubMed検索とUCSC Genome browserへのCustom Trackのアップロードを自動化してみた

はじめに

Seleniumとは、Webアプリケーションの画面操作を自動化するためのツールです。主に、Webアプリケーション開発のUIテスト時に利用するものです。また、キー入力などの操作を自動化できることから、Webスクレイピングのツールとして活用される例もあるようです。

Seleniumは、Apatch 2.0ライセンスで公開されているオープンソースのツールです。
https://www.seleniumhq.org/about/license.jsp

Seleniumの内部で使われているWebDriverは、Webブラウザを外部から遠隔操作するためのインターフェースであり、W3Cによって標準化されています(厳密には、標準化された内容と乖離する部分あり?)。
https://www.w3.org/TR/webdriver/

Selenium2では、Selenium RCと呼ばれる古い実装が残っていましたが、2016年に公開されたSelenium3では、完全にWebDriverの実装に移行しました。古い記事では、Selenium RCでの操作方法が記載されており、これは現在では動作しない方法になるので注意が必要です。

本来はUIテスト用のツールですが、今回は研究室時代にめんどくさいと思っていた作業を自動化してみました。1つはPubMedによるAdvanced Search、もう1つはUCSC Genome BrowserにCustom trackをアップロードする作業です。繰り返し同じことを繰り返す作業に対して、こういった自動化の方法は役に立ちますね。

Selenium実行サンプル

PubMed検索の自動化

selenium-test.gif (753.1 kB)

UCSC Genome BrowserへのCustom Trackのアップロード

selenium-test2.gif (834.3 kB)

実行環境・ツール

Mac OSX Sierra (v10.12.6)

  • Selenium Client for Java (v3.10.0)
  • ChromeDriver (v2.35)
  • GeckoDriver (v0.19.0)
  • SafariDriver + Safari (v11.0.3)

Windows10 (Build 16299)

Seleniumの導入

Seleniumを動かすのに必要なものは以下の通りです。

  • Selenium Client & WebDriver Language Bindings
  • 各種ブラウザのWebDriver

今回はJavaでの例を示したいと思いますが、javaであれば、MavenやGradleを使って導入する方法もあります。ただ、今回はJARファイルをダウンロードして1からプロジェクトを作っていきます。

Selenium Client & WebDriver Language Bindings

Seleniumは、JavaC#RubyPythonJavascript (Node)を公式でサポートしており、それぞれの言語についてSeleniumAPIが使えるライブラリ(Selenium Client)を用意しています。

まず、以下のサイトからJavaSelenium Clientのファイルをダウンロードします。 selenium-java-3.xx.xx.zipというファイルをダウンロードできるはずです。
https://www.seleniumhq.org/download/

image.png (195.3 kB)

各種ブラウザのWebDriver

続いて、各種ブラウザのWebDriverをダウンロードします。私の使っているPCはMac OSXなので、とりあえずFireFoxGoogle ChromeSafariのWebDriverをそれぞれダウンロードすることにします(自身のパソコンにそれぞれのブラウザがすでにインストール済みでであることを前提とします)。

image.png (310.2 kB)

余談ですが、WebDriverはSeleniumを開発しているグループが作成しているわけではなく、Webブラウザの開発元であるGoogleMozillaAppleMicrosoftなどがそれぞれ開発をしています。そのため、基本的に最新バージョンのWebブラウザに対応するWebDriverを、これらのITベンダーが提供してくれる状態にあります。こういった点も、Seleniumを使うメリットですね。

Mozilla GeckoDriver (FireFox) (Selenium3.5以降でのみ動作)

以下からダウンロードします。
https://github.com/mozilla/geckodriver/releases

自身のパソコンのOSに合ったWebDriverをダウンロードしてきます。

image.png (251.7 kB)

以下のコマンドでファイルを解凍します。

$ tar zxvf geckodriver-v0.19.1-macos.tar.gz

geckodriverという名前のWebDriverの実行ファイルが解凍されます。

Google Chrome Driver (Google Chrome)

以下からダウンロードします。
https://sites.google.com/a/chromium.org/chromedriver/

image.png (410.3 kB)

WebDriverをインストールする際は、Google Chromeのバージョンに気をつけてください。最新のものだと、対応しているバージョンはv62-64に限定されます(もちろん、以前のバージョンのWebDriverについてもダウンロード可能です)。自分のパソコンにインストールされているGoogle Chromeのバージョンを確認し、古いバージョンであれば、そのバージョンをサポートしているWebDriverをダウンロードしてください。

image.png (334.8 kB)

自身のパソコンのOSに合ったWebDriverをダウンロードしてきます。 image.png (175.0 kB)

以下のコマンドでファイルを解凍します。

$ unzip chromedriver_mac64.zip

chromedriverという名前のWebDriverの実行ファイルが解凍されます。

SafariDriver (Safari)

Mac OSX内にすでにインストール済みです。
/usr/bin/safaridriverの場所に存在します。

Safariの設定を変更する必要があります。 まず、Safariの環境設定を開きます。 image.png (67.6 kB)

次に、「メニューバーに'開発'メニューを表示」にチェックをつけます。 image.png (362.8 kB)

すると、メニューバーに「開発」が追加されるので、そこから「リモートオートメーションを許可」をクリックします。これで、ブラウザ側の設定は完了です。 image.png (1.1 MB)

リモートオートメーションを許可していない場合、Javaのテストコードを実行すると、以下のようなエラーが出力されます。このエラーが出た場合は、上記の設定ができてないので、設定を変更してください。

org.openqa.selenium.SessionNotCreatedException: Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver. (WARNING: The server did not provide any stacktrace information)

Microsoft Edge

以下からダウンロードします。
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

image.png (389.2 kB)

自身のパソコンのOSのビルドに合ったWebDriverをダウンロードしてきます。 image.png (120.6 kB)

Internet Explorer 11

設定が複雑なので、必要でない限り使わないほうが良いと思います。

こちらに詳しい使用方法が記載されているので参照してください。 保護モードの設定が、「インターネット」「イントラネット」「信頼済みサイト」「制限付きサイト」の4つで統一されていることがかなり重要です(この設定が揃っていないとWebDriverが動作しません)。

seleniumでinternet-explorer11を動かす方法

http://bitwave.showcase-tv.com/seleniumでinternet-explorer11を動かす方法/

トラブルシューティング(一部)

画面は拡大せずに、100%でないと動作しません。以下のエラーが出た場合は、拡大率を100%にしましょう。

org.openqa.selenium.SessionNotCreatedException: Unexpected error launching Internet Explorer. Browser zoom level was set to 110%. It should be set to 100%

image.png (26.9 kB)

Seleniumを動かしてみる

以下では、Eclipseがインストール済みであることを前提として説明を行います。 素のEclipseをインストールするのではなく、以下のAll-in-Oneのパッケージ(Pleiades All in One)をインストールすることをお勧めします。
http://mergedoc.osdn.jp/

1. プロジェクトファイルの作成

Seleniumを動かすためのプロジェクトファイルを作成します。 [新規] -> [Javaプロジェクト]をクリックします。 image.png (70.3 kB)

適当なプロジェクト名をつけて、「次へ」をクリックします。 image.png (51.9 kB)

先ほどダウンロードしたSelenium Clientを解凍し、libsフォルダのjarとclient-combined-3.10.0.jarclient-combined-3.10.0-sources.jarをそれぞれプロジェクトファイルに取り込みます。

image.png (86.4 kB)

まず、「ライブラリ」タブを選択し、「外部JARの追加」をクリックします。 image.png (41.3 kB)

上述のSelenium ClientのJARファイル一式を追加します。 最後に、「完了」ボタンをクリックし、プロジェクトを生成します。 image.png (75.1 kB)

すると、参照ライブラリに先ほど取り込んだSelenium ClientのJARファイルが参照されて取り込まれていることが確認できると思います。

image.png (51.5 kB)

次に、WebDriverを保存するためのフォルダを用意します。 [新規] -> [フォルダー]をクリックします。

image.png (117.2 kB)

フォルダー名を「exe」として、「完了」ボタンをクリックします。 image.png (25.0 kB)

作成した「exe」フォルダ内に、先ほどダウンロードしたWebDriverをドラック&ドロップでインポートします。(ここでは、chromedriver.exeをインポートした例を示した。)

image.png (13.3 kB)

Mac OSXの場合、実行権限を付与しておきます。 image.png (58.4 kB)

$ chmod 755 geckodriver

続いて、Seleniumを実行するためのテストクラスを作成していきます。 プロジェクトの「src」フォルダを右クリックし、[新規] -> [Junitテスト・ケース]をクリックします。

image.png (80.9 kB)

適当なパッケージ名とクラス名を記入し、setUp()tearDown()にチェックを付けます。

image.png (47.3 kB)

JUnit4がビルドパスに入っていない場合、追加するかどうか聞かれるので、「OK」をクリックしてビルドパスに加えます。

image.png (20.0 kB)

2. PubMedUCSC Genome Browserを操作するコードを書いてみる

ページオブジェクトパターン

下図にページオブジェクトパターンと呼ばれる、一般的なクラスの設計方法を示しました。この方法を取り入れることで、メニューやボタン、検索入力欄など、Webページへの操作を共通クラスにまとめることでメンテナンス性の高いコードを書くことができます。

image.png (538.4 kB)

ロケータの調べ方

selenium用のコードを書くために、まずロケータ(ボタンやメニューなどを操作するための目印)を調べる必要があります。例えば、FireFoxを使うと、要素(下の例だと"Advanced")を右クリックして「要素を調査」をクリックすることでロケータを調べることができます。

image.png (353.4 kB)

どのタグが使われているかなどの情報を調べることができます(以下の図だと、INPUTタグのID要素が"Submit"であることがわかります。これを目印にしてSeleniumでWebブラウザを操作していきます)。

image.png (682.9 kB)

コーディング

以下のような構成で、プログラムを用意しました。 pageパッケージにページオブジェクトクラスを、testパッケージにJUnitのテストケースクラスを配置するようにしました。

image.png (36.0 kB)

WebDriverの呼び出し

System.setProperty()の2番目の引数は、ダウンロードしたWebDriverを指定してください。OSによって、拡張子が異なるので注意する必要があります。以下でいくつか例を示しました。

Google Chrome (Mac OSX)
System.setProperty("webdriver.chrome.driver", "exe/chromedriver");
WebDriver driver = new ChromeDriver();
Firefox (Mac OSX)
System.setProperty("webdriver.gecko.driver", "exe/geckodriver");
WebDriver driver = new FirefoxDriver();
Safari (Mac OSX)
WebDriver driver = new SafariDriver();
Microsoft Edge (Windows10)
System.setProperty("webdriver.edge.driver", "exe/MicrosoftWebDriver.exe");
WebDriver driver = new EdgeDriver();
Internet Explorer (Windows10)
System.setProperty("webdriver.ie.driver", "exe/IEDriverServer.exe");
WebDriver driver = new InternetExplorerDriver();

ソースコード

ソースコードの内容について言及しません。 主に、「Selenium実践入門」と言う本と下記のWebサイトを参考にしました。

PubMedSearchTest.java
package test;

import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import page.PubMedAdvancedSearchPage;

public class PubMedSearchTest {

    private WebDriver driver;

    @Before
    public void setUp() throws Exception {
        System.setProperty("webdriver.chrome.driver", "exe/chromedriver.exe");
        driver = new ChromeDriver();
        //System.setProperty("webdriver.edge.driver", "exe/MicrosoftWebDriver.exe");
        //driver = new EdgeDriver();
        //System.setProperty("webdriver.ie.driver", "exe/IEDriverServer.exe");
        //driver = new InternetExplorerDriver();

        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
    }

    @After
    public void tearDown() throws Exception {
        //driver.quit();
    }

    @Test
    public void pubmedAdvancedSearchTest() {
        // PubMed Top
        PubMedAdvancedSearchPage pmPage = new PubMedAdvancedSearchPage(driver);

        // Go to Advanced Search page
        pmPage.goToAdvancedSearch();

        // Set keywords
        pmPage.setJournal("Nature communications");
        pmPage.setJournal("Nature biotechnology");
        pmPage.setSearchSelect(1, "OR");
        pmPage.setJournal("Nature methods");
        pmPage.setSearchSelect(2, "OR");
        pmPage.setJournal("Nature genetics");
        pmPage.setSearchSelect(3, "OR");
        pmPage.setJournal("Molecular cell");
        pmPage.setSearchSelect(4, "OR");
        pmPage.setJournal("eLife");
        pmPage.setSearchSelect(5, "OR");
        pmPage.setJournal( "PLoS biology");
        pmPage.setSearchSelect(6, "OR");
        pmPage.setJournal("Genome research");
        pmPage.setSearchSelect(7, "OR");
        pmPage.setJournal("Genes & development");
        pmPage.setSearchSelect(8, "OR");
        pmPage.setJournal("Nature cell biology");
        pmPage.setSearchSelect(9, "OR");

        // Click Search button
        pmPage.clickSearchButton();
    }

}
UCSCGenomeBrowserTest.java
package test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import page.UCSCGenomeBrowserUploadPage;

public class UCSCGenomeBrowserTest {

    private WebDriver driver;

    @Before
    public void setUp() throws Exception {
        System.setProperty("webdriver.chrome.driver", "exe/chromedriver.exe");
        driver = new ChromeDriver();
        //System.setProperty("webdriver.edge.driver", "exe/MicrosoftWebDriver.exe");
        //driver = new EdgeDriver();
        //System.setProperty("webdriver.ie.driver", "exe/IEDriverServer.exe");
        //driver = new InternetExplorerDriver();
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void test() {
        UCSCGenomeBrowserUploadPage gmPage = new UCSCGenomeBrowserUploadPage(driver);
        gmPage.goToCustomTrack();

        gmPage.setGenomeRefSelect("hg19");

        // Upload file
        gmPage.UploadFile("C://Users/imama/Desktop/test1.bed");
        gmPage.submit();

        // Back to custom track page
        gmPage.goBackToCustomTrack();

        // Upload file
        gmPage.UploadFile("C://Users/imama/Desktop/test2.bed");
        gmPage.submit();

        // Back to custom track page
        gmPage.goBackToCustomTrack();

        // Upload file
        gmPage.UploadFile("C://Users/imama/Desktop/test3.bed");
        gmPage.submit();

    }

}
PubMedAdvancedSearchPage.java
package page;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

public class PubMedAdvancedSearchPage {

    /* WebDriverクラスのインスタンス */
    private WebDriver driver;

    // 明示的な待機
    WebDriverWait wait;

    // キーワードカウンタ
    private Integer keywordCounter;

    // コンストラクタ
    public PubMedAdvancedSearchPage(WebDriver driver){
        this.driver = driver;
        this.keywordCounter = 0;
        this.wait = new WebDriverWait(driver, 10);
    }

    // Advanced saerch画面へ遷移
    public void goToAdvancedSearch() {
        driver.get("https://www.ncbi.nlm.nih.gov/pubmed/");
        driver.findElement(By.linkText("Advanced")).click();

        // Goto PubMed Advanced search
        String previousURL = driver.getCurrentUrl();
        System.out.println(previousURL);
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        ExpectedCondition<Boolean> e = new ExpectedCondition<Boolean>() {
              public Boolean apply(WebDriver d) {
                return (d.getCurrentUrl() != previousURL);
              }
        };
        wait.until(e);
        String currentURL = driver.getCurrentUrl();
        System.out.println(currentURL);

        // ページタイトルが変更されるまで待ち
        wait.until(ExpectedConditions.titleContains("Advanced search"));
    }

    // Set journal
    public void setJournal(String journal) {
        // FieldにJournalを選択
        Select select = new Select(driver.findElement(By.id("ff_" + keywordCounter)));
        select.selectByValue("Journal");

        // Journal名を入力
        WebElement searchBox = driver.findElement(By.id("fv_" + keywordCounter));
        searchBox.sendKeys(journal);

        // カウントアップ
        keywordCounter += 1;
    }

    // Set search select
    public void setSearchSelect(Integer id, String value) {
        Select select = new Select(driver.findElement(By.id("fop_" + id)));
        select.selectByValue(value);
    }

    // Click Search button
    public void clickSearchButton() {
        driver.findElement(By.id("search")).click();
    }
}
UCSCGenomeUploadPage.java
package page;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

public class UCSCGenomeBrowserUploadPage {

    /* WebDriverクラスのインスタンス */
    private WebDriver driver;

    // 明示的な待機
    WebDriverWait wait;

    // コンストラクタ
    public UCSCGenomeBrowserUploadPage(WebDriver driver){
        this.driver = driver;
        this.wait = new WebDriverWait(driver, 10);

        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
    }

    // Go to Custom track page
    public void goToCustomTrack() {
        driver.get("https://genome.ucsc.edu/");
        driver.findElement(By.id("myData")).click();

        wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("customTracksMenuLink")));
        driver.findElement(By.id("customTracksMenuLink")).click();
    }

    // Upload file
    public void UploadFile(String filePath) {
        WebElement upload = driver.findElement(By.name("hgt.customFile"));
        upload.sendKeys(filePath);
    }

    // Submit
    public void submit() {
        driver.findElement(By.id("Submit")).click();
    }

    // Return Custom track page
    public void goBackToCustomTrack() {
        WebDriverWait wait2 = new WebDriverWait(driver, 10000);
        wait2.until(ExpectedConditions.visibilityOfElementLocated(By.id("addTracksButton")));
        driver.findElement(By.id("addTracksButton")).click();
    }

    public void setGenomeRefSelect(String genomeRef) {
        Select select = new Select(driver.findElement(By.id("db")));
        select.selectByValue(genomeRef);
    }
}

スクリーンショットの取り方について(トラブルシューティング

余談ですが、Java8の場合、FileUtils(Java7以前)ではなく、FileHandler(Java8以降)なので間違いがないように。 https://github.com/SeleniumHQ/selenium/issues/4919

File tmpFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
    FileHandler.copy(tmpFile, new File("/Users/imamachinaoto/Desktop/test.png"));
} catch (IOException e) {
    // TODO 自動生成された catch ブロック
    e.printStackTrace();
}

参考

[初心者向け] JavaSeleniumを動かす
https://qiita.com/tsukakei/items/41bc7f3827407f8f37e8

selenium get current url after loading a page
https://stackoverflow.com/questions/16242340/selenium-get-current-url-after-loading-a-page

Selenium WebDriverのwaitを活用しよう
http://softwaretest.jp/labo/tech/labo-294/

Best Practices & Tips: Selenium File Upload
https://saucelabs.com/resources/articles/best-practices-tips-selenium-file-upload