Rhythm & Biology

Engineering, Science, et al.

Dockerでapacheを動かす

Dockerのコンテナでapacheを動かすまでのメモ

環境

ファイル構成

vagrant$ find .
.
./Dockerfile
./htdocs
./htdocs/index.html

vagrant$ cat htdocs/index.html
<!DOCTYPE html>
<html>
  <body>
    <h1>Hello Docker!</h1>
  </body>
</html>

Dockerfile

  • ubuntu:12.04ベース
  • aptでapache2をインストール
  • ホストのhtdocsディレクトリの中身をコンテナの/var/www配下に転送
  • 80番ポートをexpose
  • コンテナ起動時にapacheを起動
FROM ubuntu:12.04

MAINTAINER mythosil

RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y install apache2

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2

ADD ./htdocs /var/www

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

イメージ作成

"apache"という名前でイメージ作成

vagrant$ docker build -t apache .

(vagrantユーザをdockerグループに入れてあるのでsudo不要)

コンテナ起動

ホストの8080番ポートからコンテナの80番ポートへリダイレクト

vagrant$ docker run -p 8080:80 -d apache

apacheへアクセス

vagrantで起動したubuntuのIPは192.168.33.10としています。

osx$ curl http://192.168.33.10:8080/
<!DOCTYPE html>
<html>
  <body>
    <h1>Hello Docker!</h1>
  </body>
</html>

vagrantで起動しているUbuntuを通してコンテナ内のapacheへアクセスできました。

ログの取り出し

vagrant$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                  NAMES
19ac2f09725a        apache:latest       /usr/sbin/apache2 -D   34 minutes ago      Up 34 minutes       0.0.0.0:8080->80/tcp   ecstatic_fermat
vagrant$ docker cp 19ac2f09725a:/var/log/apache2 .
vagrant$ ls apache2
access.log  error.log  other_vhosts_access.log

コンテナ停止

vagrant$ docker stop 19ac2f09725a

参考

さくらVPS(CentOS6.4)でDockerを使う

Docker 0.7からaufs以外のstorage driverがサポートされてCentOSでもDockerが使えるようになりました。
aufsがサポートされていなければ、起動時にdevicemapperを利用してくれるとのことです。devicemapperもサポートされていなければvfsを利用。

CentOSにはepel使って簡単にインストールできるようになったので、さくらVPSで使ってみました。

# CentOSのバージョンは6.4
$ cat /etc/redhat-release
CentOS release 6.4 (Final)

インストール・起動

epelリポジトリが登録されていればyum一発で入ります。

$ sudo yum -y install docker-io
$ sudo service docker start

centosイメージを取得

$ sudo docker pull centos
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              6.4                 539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)
centos              latest              539c0211cd76        8 months ago        300.6 MB (virtual 300.6 MB)

mysql-serverをインストール(失敗)

Dockerfileを書いてmysql-serverをインストールしてみます。

$ cat Dockerfile
FROM centos
RUN yum -y install mysql-server
$ sudo docker build -t mysql-server .
...(省略)...
Error: Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again
Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os error was
14: PYCURL ERROR 6 - "Couldn't resolve host 'mirrorlist.centos.org'"
Error build: The command [/bin/sh -c yum -y install mysql-server] returned a non-zero code: 1

エラー・・・

コンテナが参照するDNSを変更

上記エラーについて深く追ってはいないのですが、DNSを変更すればうまく動きました。
考えられるやり方は2つ。

  • /etc/resolv.confを書き換えたイメージ作成してそれを利用
  • dockerサービス起動時のオプションでDNS指定

今回は後者でいきます。

# 起動時オプションを指定
$ cat /etc/sysconfig/docker
other_args="-dns 8.8.8.8"
# dockerサービス再起動
$ sudo service docker restart

mysql-serverをインストール(成功)

Dockerfileは全くいじる必要ありません。

$ sudo docker build -t mysql-server .
...(省略)...
Loaded plugins: fastestmirror
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package mysql-server.x86_64 0:5.1.71-1.el6 will be installed
...(省略)...
Complete!
 ---> 2e4d9c9867c3
Successfully built 2e4d9c9867c3

補足

Dockerfileで構築する場合("docker build"でやる場合)には、dockerサービスの起動時オプションでDNSを指定する必要があります。
"docker run"の場合は引数でDNSを指定できます。

$ sudo docker run -dns 8.8.8.8 -t centos ping -c 3 yahoo.co.jp

感想

VPSが貧弱だからか、それともaufsが使えないからなのか分からないのですが、コンテナ起動に時間がかかります・・・。

CentOS6.4ではstorage driverにvfsを使うようです。

$ sudo docker info
Containers: 1
Images: 2
Driver: vfs

選択文字列を検索するChrome Extension

選択文字列をキーバインド一発でYahooなりGoogleなりで検索する方法が無いかなと思って探してみたけれども、意外と見つからなかったので作ってしまいました。

Chromeのデフォルトの機能として、選択文字列を右クリックすれば検索するメニューが表示されますが、この1アクションさえも面倒くさいと感じる人は少なくないと思います。
他にも選択文字列を検索するextensionはありますが、検索エンジンを選択するポップアップが表示されたりと、結局1アクション余分なものしか見つかりませんでした。

今回作ったExtensionの機能はシンプルなもので、文字列を選択した状態で「Command+Enter」を押せば、新しいタブでYahooでの検索結果が表示されるというものです。

https://github.com/mythosil/chrome-selection-search

ファイル構成

  • chrome-selection-search/
    • manifest.json
    • selection-search.js
    • background.js

manifest.json

{
  "manifest_version": 2,
  "name": "Selection-Search",
  "description": "Search the selected words in a new tab",
  "version": "1.0",
  "background": {
    "persistent": false,
    "scripts": [ "background.js" ]
  },
  "content_scripts": [{
    "matches": [ "http://*/*", "https://*/*" ],
    "js": [ "selection-search.js" ]
  }]
}

タブ操作には通常パーミッションが必要となりますが、今回はchrome.tabs.createしか使わないため不要です。

selection-search.js

window.addEventListener('keydown', function(e) {
  if (e.metaKey && e.keyCode == 13) {
    var text = window.getSelection().toString();
    if (text.length > 0) {
      chrome.extension.sendMessage({ text: text }, function(response) {});
    }
  }
}, false);

macのCommandキーが押されていると、e.metaKeyがtrueとなります。
EnterキーのkeyCodeは13です。
この部分は好みのキーバインドに書き換えて使ってください。

background.js

chrome.extension.onMessage.addListener(function(req, sender, callback) {
  if (sender.tab) { // from a content script
    if (req.text !== undefined) {
      var url = encodeURI("http://search.yahoo.co.jp/search?ei=UTF-8&fr=crmas&p=" + req.text);
      var properties = { url: url };
      chrome.tabs.create(properties, function(tab) {});
    }
  }
});

補足

content script内ではchrome.tabsがundefinedとなっているため、backgroundにメッセージを投げてタブ操作をさせるというややこしいことをしています。
実際は、こんなまわりくどいことをしなくても、window.openを使えばbackground.jsは不要です。
メッセージパッシングを使ってみたかっただけです。

疑問

検索エンジンが決めうちになっていますが、Chromeのデフォルトで設定されている検索エンジンを使いたいです。これを取得するAPIはあるのでしょうか。