CentOS 7の仮想化、Docker、リソース管理(後編)

2015年1月30日(金)
古賀 政純

巷で話題のDockerとは?

最近、巷で注目を浴びているオープンソースの一つに「Docker」(ドッカー)があります。Dockerは、コンテナと呼ばれる隔離空間を管理するためのツールです。CentOS 7は、この「コンテナ」と呼ばれるアプリケーションとOSをパッケージ化した実行環境をサポートしています。一般的に、Linux OS上での隔離空間を「Linuxコンテナ」と呼びます。Linuxコンテナは、KVMやXenなどのハイパーバイザー型の仮想化技術に比べて、CPU、メモリ、ストレージ、ネットワーク等のハードウェア資源の消費やオーバーヘッドが小さいとう利点が挙げられます。Dockerは、Linuxコンテナの機能に加えて、API、イメージフォーマット、環境を配布する仕組みを持っています。しかし、このDockerが注目される理由は、ハードウェア資源の消費のオーバーヘッドが小さいだけではありません。Dockerが注目される背景には、アプリケーション開発者が最も嫌うであろう「ハードウェアの調達やメンテナンス」の隠蔽が挙げられます。ハードウェアに関する部分は、アプリケーション開発者にとってあまり重要ではありません。従来のKVM等による仮想化は、アプリケーション開発者にとってのメリットというよりもむしろ、システム管理者にとって大きなメリットがありました。一方、Dockerのような軽量なコンテナ技術の発達により、アプリケーション単位での隔離、開発環境の容易な作成と廃棄ができるようになり、アプリケーションのメンテナンスの簡素化がより一層進むことになります。これは、システム管理者よりもアプリケーション開発者にとってのメリットが非常に大きいことを意味します。また、Dockerの仕組みによって、アプリケーションの開発と実環境への素早い展開と運用の両立が見えてきました。これは、近年、開発者やIT部門の間で話題になっている「DevOps環境」の実現に他なりません。アプリケーション開発者やIT部門にとっては、アプリケーションの開発、運用、廃棄等を、ハードウェア資源を意識しない「雲」の上で迅速に行える環境がDockerを使って整備されつつあります。

物理基盤、仮想化基盤、PaaS基盤の比較。PaaS基盤では、DevOpsのようなアプリケーション中心の考えで隔離空間毎に異なるOSバージョンとサービスを提供できる

図6:物理基盤、仮想化基盤、PaaS基盤の比較。PaaS基盤では、DevOpsのようなアプリケーション中心の考えで隔離空間毎に異なるOSバージョンとサービスを提供できる

CentOS 7でdockerを使う

以下では、CentOS 7で採用されているdockerのインストールと基本的な利用方法について説明します。CentOS 7では、dockerパッケージが標準で含まれています。yumコマンドでインストールします。

# yum install -y docker
# rpm -qa |grep docker
docker-1.3.2-4.el7.centos.x86_64

docker pull centosでイメージをインターネット経由で入手しますが、もし企業内においてプロキシーサーバー経由でインターネットに接続する環境では、以下のように、/etc/sysconfig/dockerファイルにプロキシーサーバーを指定し、dockerサービスを再起動してください。

# vi /etc/sysconfig/docker
…
http_proxy=http://proxy.jpn.hp.com:8080
https_proxy=http://proxy.jpn.hp.com:8080
…

# systemctl restart docker
# docker pull centos

dockerサービスを起動します。

# systemctl start docker
# systemctl enable docker
ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service'

これでDockerのインストールは完了です。Dockerでは、様々なOSとアプリケーションがパッケージ化された環境がDockerイメージとしてDockerリポジトリに用意されています。イメージファイルを一から作成することも可能ですが、すでにDockerリポジトリに用意されているイメージファイルを利用することができますので、コンテナへのOSやアプリケーションのインストール等の煩雑な作業をスキップすることができます。以下では、Dockerリポジトリに用意されているイメージファイルをDocker上で起動させてみます。
イメージファイルをDockerリポジトリから入手する前にSELinuxをdisableにしておきます。

# setenforce 0
# getenforce
Permissive

イメージファイルをインターネット経由でDockerリポジトリから入手します。

# docker pull centos:centos5
Pulling repository centos
bac0c97c3010: Download complete
511136ea3c5a: Download complete
5b12ef8fd570: Download complete
Status: Downloaded newer image for centos:centos5

# docker pull centos:centos6
Pulling repository centos
510cf09a7986: Download complete
511136ea3c5a: Download complete
5b12ef8fd570: Download complete
Status: Downloaded newer image for centos:centos6

# docker pull centos:centos7
Pulling repository centos
8efe422e6104: Download complete
511136ea3c5a: Download complete
5b12ef8fd570: Download complete
Status: Downloaded newer image for centos:centos7

Dockerリポジトリから入手し、ローカルのCentOS 7サーバー上に保管されているイメージファイル一覧を確認します。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              5                   bac0c97c3010        7 days ago          466.9 MB
centos              centos5             bac0c97c3010        7 days ago          466.9 MB
centos              6                   510cf09a7986        7 days ago          215.8 MB
centos              centos6             510cf09a7986        7 days ago          215.8 MB
centos              latest              8efe422e6104        7 days ago          224 MB
centos              7                   8efe422e6104        7 days ago          224 MB
centos              centos7             8efe422e6104        7 days ago          224 MB

上記のイメージファイル群のうち、centos6という名前の付いたタグの付いたイメージファイルから、コンテナを生成、起動し、そのコンテナ内で作業できるようにしてみましょう。Dockerのイメージファイルからコンテナを起動するには、docker runを実行します。--nameオプションに、コンテナの名前を指定します。今回は、test01という名前のコンテナを起動するように指定しました。-iオプションは、コンテナの標準入力を開いた状態にします。-tオプションを付与することにより、Dockerは、仮想端末を割り当てて、コンテナの標準入力にアタッチします。centos:centos6は、入手したイメージファイルのタグ付きのリポジトリ名です。最後に、/bin/bashを指定することで、コンテナ上のシェルを起動します。

# docker run --name test01 -i -t centos:centos6 /bin/bash
[root@d962dc3be270 /]#

コンテナにログインし、作業してみます。コンテナのOSのバージョンを確認します。

[root@d962dc3be270 /]# cat /etc/redhat-release
CentOS release 6.6 (Final)

すると、CentOS 6.6であることがわかります。ホスト名を確認してみます。

[root@d962dc3be270 /]# hostname
d962dc3be270

ホスト名は自動的に「d962dc3be270」という名前で割り振られていることがわかります。さらにIPアドレスを確認し、ホストOSや外部と通信できるかを確認します。dockerでは、標準で、インタフェースdocker0を割り当てます。

[root@d962dc3be270 /]# ifconfig eth0 |grep inet
          inet addr:172.17.0.5  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link
[root@d962dc3be270 /]# ping -c 3 172.16.1.1
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=63 time=0.690 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=63 time=0.281 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=63 time=0.239 ms

--- 172.16.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2373ms
rtt min/avg/max/mdev = 0.239/0.403/0.690/0.204 ms
[root@d962dc3be270 /]# nslookup www.hp.com<http://www.hp.com>

dockerのイメージファイルの仕組みを理解するため、まず、試しいdockerコンテナー上の/rootディレクトリにファイルtestfileを作成しておきます。

[root@d962dc3be270 /]# touch /root/testfile
[root@d962dc3be270 /]# ls /root/
testfile

dockerコンテナのOS環境から離脱します。

[root@d962dc3be270 /]# exit
exit
#

ホストOS上で、過去に起動したコンテナ一覧を確認します。

# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
d962dc3be270        centos:6            "/bin/bash"         9 minutes ago       Exited (0) About a minute ago                       test01

先程作業したコンテナを再利用できるように、コンテナのイメージ化を行います。コンテナをイメージ化するには、コンテナをコミットします。先程作業したコンテナのコンテナIDとイメージを指定してコミットを行います。

# docker commit d962dc3be270 centos:centos6
5468f0e1072fbd5cdf0042efc76e3d0d8c778f235faf212bcbf9b2105ebdf30f

再び、現在のイメージファイルの一覧を確認します。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              centos6             5468f0e1072f        24 seconds ago      215.8 MB
centos              centos5             bac0c97c3010        7 days ago          466.9 MB
centos              5                   bac0c97c3010        7 days ago          466.9 MB
centos              6                   510cf09a7986        7 days ago          215.8 MB
centos              centos7             8efe422e6104        7 days ago          224 MB
centos              latest              8efe422e6104        7 days ago          224 MB
centos              7                   8efe422e6104        7 days ago          224 MB

先程コミットしたイメージファイル「centos:centos6」を使って、別のコンテナtest02を生成してみます。

# docker run --name test02 -i -t centos:centos6 /bin/bash
[root@5b2ac9622d6f /]#

コンテナtest02上の/rootを確認してみます。

[root@5b2ac9622d6f /]# ls /root/
testfile
[root@5b2ac9622d6f /]#

コンテナtest02で、/root/testfile2を作成します。

[root@5b2ac9622d6f /]# touch /root/testfile2
[root@5b2ac9622d6f /]# exit
exit
# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
5b2ac9622d6f        centos:centos6      "/bin/bash"         2 minutes ago       Exited (0) About a minute ago                       test02
d962dc3be270        centos:6            "/bin/bash"         20 minutes ago      Exited (0) 12 minutes ago                           test01

# docker commit 5b2ac9622d6f centos:testfile2
4eac0fb23ec1d4a212b4aa289637f43da3049dd975d48a91fd9890ca6a368cdd
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              testfile2           4eac0fb23ec1        8 seconds ago       215.8 MB
centos              centos6             5468f0e1072f        7 minutes ago       215.8 MB
centos              5                   bac0c97c3010        7 days ago          466.9 MB
centos              centos5             bac0c97c3010        7 days ago          466.9 MB
centos              6                   510cf09a7986        7 days ago          215.8 MB
centos              centos7             8efe422e6104        7 days ago          224 MB
centos              latest              8efe422e6104        7 days ago          224 MB
centos              7                   8efe422e6104        7 days ago          224 MB

上記より、作業を行ったコンテナをコミットすることでその作業内容を反映したイメージファイルが生成でき、さらに作成したイメージファイルを再利用して、新たなコンテナを生成できていることがわかります。開発者は、アプリケーション毎に異なるコンテナを複数作成し、コミットしておけば、そのアプリケーションに特化したイメージファイルを持つことができ、すぐにアプリケーションが実行可能な環境をコンテナで利用することができます。

ホストマシンに保管されたDockerイメージからdocker runでコンテナを起動する。起動したコンテナで作業を施し、アプリケーション等の構築をしたものをdocker commitでDockerイメージとして登録する

図7:ホストマシンに保管されたDockerイメージからdocker runでコンテナを起動する。起動したコンテナで作業を施し、アプリケーション等の構築をしたものをdocker commitでDockerイメージとして登録する

コンテナに含まれるファイルの確認方法

現在起動しているDockerコンテナのファイルシステム上にあるファイル等をホストマシンから確認したい場合があります。起動中のコンテナのファイルシステムは、/var/lib/docker/devicemapper/metadataディレクトリ配下にあるコンテナID の名前が付いたメタデータの情報を元に、Device Mapperを使ってアクセスできます。以下は、CentOS 6.6のDockerイメージからコンテナを起動し、そのコンテナのファイルシステムに存在する/etc/redhat-releaseファイルに記載されたCentOSのバージョンをホストマシンから確認する手順です。まず、Dockerに現在登録されているイメージファイルを確認します。今回、CentOS 6.6のDockerイメージ「centos:centos6.6」は、事前にCentOS 6のDockerイメージを入手し、yum updateによりパッケージを最新に更新することにより作成しました。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              centos6.6           6e80aa2dad3a        23 seconds ago      215.8 MB
centos              testfile2           4eac0fb23ec1        4 minutes ago       215.8 MB
centos              centos6             5468f0e1072f        12 minutes ago      215.8 MB
centos              5                   bac0c97c3010        7 days ago          466.9 MB
centos              centos5             bac0c97c3010        7 days ago          466.9 MB
centos              6                   510cf09a7986        7 days ago          215.8 MB
centos              centos7             8efe422e6104        7 days ago          224 MB
centos              7                   8efe422e6104        7 days ago          224 MB
centos              latest              8efe422e6104        7 days ago          224 MB

上記のDockerイメージ「centos:centos6.6」から、コンテナを起動します。コンテナ名はtest001としました。

# docker run --name test0001 -i -t centos:centos6.6 /bin/bash
[root@098686019f0d /]#

ホストマシンの別の端末で、起動中のコンテナを確認します。

# docker ps -a
CONTAINER ID    IMAGE           COMMAND         CREATED         STATUS  PORTS           NAMES
098686019f0d    centos:centos6.6        "/bin/bash"     12 minutes ago  Up      12 minutes      test001

以下は、起動中のコンテナ「098686019f0d」のファイルシステムをホストマシンから確認する手順です。まず、コンテナ「098686019f0d」のメタデータから、コンテナのデバイスIDとサイズを確認します。

# cd /var/lib/docker/devicemapper/metadata
# cat 098686019f0dec240ec5b0473046b78b5e56cb7dd0651e821d9e9216cfa9e37e |python -mjson.tool
{
    "device_id": 6,
    "initialized": false,
    "size": 10737418240,
    "transaction_id": 121
}

上記より、このコンテナのデバイスIDは6、サイズが、10737418240であることがわかります。次に、起動しているコンテナがマウントされているループバックデバイスを表示します。

# ls -l /dev/mapper/
合計 0
crw-------. 1 root root 10, 236 12月 17 17:46 control
lrwxrwxrwx. 1 root root       7  1月 13 11:23 docker-8:3-84171797-098686019f0dec240ec5b0473046b78b5e56cb7dd0651e821d9e9216cfa9e37e -> ../dm-3
lrwxrwxrwx. 1 root root       7  1月 13 08:33 docker-8:3-84171797-pool -> ../dm-1
lrwxrwxrwx. 1 root root       7  1月 13 05:28 encrypted001 -> ../dm-2
lrwxrwxrwx. 1 root root       7  1月 13 05:28 pool001-lvol001 -> ../dm-0

上記のdocker-8:3-84171797-poolと先述のデバイスID、サイズを使って、テスト用のボリュームを作成します。具体的には、コンテナのサイズ「10737418240」と、デバイスIDの「6」をdmsetupコマンドの--tableオプションで指定します。

# dmsetup create testvol01 --table "0 $((10737418240 / 512)) thin /dev/mapper/docker-8:3-84171797-pool 6"

テスト用のボリュームtestvol01は/dev/mapperディレクトリ以下に作成されていますので、これをマウントします。

# mount /dev/mapper/testvol01 /mnt

/mntにマウントしたコンテナのディレクトリツリーと/etc/redhat-releaseファイルを確認します。

# ls -la /mnt/rootfs/
合計 176
drwxr-xr-x. 21 root root  4096  1月 13 08:07 .
drwxr-xr-x.  4 root root  4096  9月  9 06:30 ..
dr-xr-xr-x.  2 root root  4096  1月  2 23:23 bin
drwxr-xr-x.  4 root root 90112  1月  2 23:23 dev
drwxr-xr-x. 45 root root  4096  1月  2 23:23 etc
drwxr-xr-x.  2 root root  4096  9月 23  2011 home
dr-xr-xr-x.  7 root root  4096  1月  2 23:23 lib
dr-xr-xr-x.  6 root root 12288  1月  2 23:23 lib64
drwx------.  2 root root  4096  1月  2 23:21 lost+found
drwxr-xr-x.  2 root root  4096  9月 23  2011 media
drwxr-xr-x.  2 root root  4096  9月 23  2011 mnt
drwxr-xr-x.  2 root root  4096  9月 23  2011 opt
drwxr-xr-x.  2 root root  4096  1月  2 23:21 proc
dr-xr-x---.  2 root root  4096  1月  2 23:23 root
dr-xr-xr-x.  2 root root  4096  1月  2 23:23 sbin
drwxr-xr-x.  3 root root  4096  1月  2 23:23 selinux
drwxr-xr-x.  2 root root  4096  9月 23  2011 srv
drwxr-xr-x.  2 root root  4096  1月  2 23:21 sys
drwxrwxrwt.  2 root root  4096  1月  2 23:23 tmp
drwxr-xr-x. 13 root root  4096  1月  2 23:21 usr
drwxr-xr-x. 17 root root  4096  1月  2 23:21 var

# cat /mnt/rootfs/etc/redhat-release
CentOS release 6.6 (Final)

コンテナが持つファイルシステムを確認し終えたら、マウントを解除し、テスト用のボリュームは削除しておきます。

# cd
# umount /mnt
# dmsetup remove /dev/mapper/testvol01

【注意】

dmsetupコマンドにより、コンテナのファイルシステムを確認するためのテスト用のボリュームを作成する際に、デバイスIDを間違えると、別のコンテナのファイルシステムの中身を見ることになりますので十分注意して下さい。

Dockerfileを使ったイメージファイルの構築

Dockerイメージの作成や、イメージファイルからコンテナを起動する一連の手順は、先述のdockerコマンドでコマンドラインから入力することで可能ですが、イメージ作成作業、アプリケーションのインストール等の複数の作業をまとめて行いたい場合があります。そのような場合は、Dockerfileを使うと便利です。Dockerファイルは、開発環境におけるMakefileのように、一連の作業をDockerで定義された書式に従って事前に記述し、それに基づいてイメージの作成を行います。以下では、CentOS 7で稼働するApache Webサーバーが起動するコンテナのイメージファイルの作成、コンテナの起動、コンテナへのアクセス方法を述べます。まず、Apacheが稼働するコンテナ用のDockerfileを用意します。今回は、/root/apacheディレクトリを作成し、その下にDockerfileを作成します。

# mkdir /root/apache
# cd /root/apache
# vi Dockerfile
FROM            centos:centos7  ←使用するDockerイメージ名を指定
MAINTAINER      Masazumi Koga
ENV             container       docker
RUN             yum swap -y     fakesystemd systemd ←systemdをDockerイメージにインストール
RUN             yum install -y  initscripts
RUN             yum install -y  httpd   ←Apache WebサーバーのhttpdパッケージをDockerイメージにインストール
RUN             echo "Hello Apache." > /var/www/html/index.html ←テスト用のHTMLファイルをDockerイメージに配置
RUN             systemctl enable httpd ←コンテナ起動時にhttpdサービスが起動するように設定
EXPOSE          80 ←Dockerコンテナが外部に開放するポート番号を指定

Dockerfile内では、FROM行に利用するイメージの種類を記述します。イメージ名はコマンドラインから「docker images」で確認可能ですので、一覧に表示されているイメージ名を記述します。ここではCentOS 7のイメージ「ceentos:centos7」を指定しています。RUN行では、Dockerのイメージを作成する際に実行したいコマンドを記述します。今回、RUN行に、「yum swap -y fakesystemd systemd」が指定されています。Dockerリポジトリに標準で用意されているCentOS 7のDockerイメージは、デフォルトでsystemdを利用しないものが用意されています。しかし、多くのCentOS 7向けのアプリケーションやサービスがsystemdを使用するため、Dockerイメージにsystemdをインストールしたい場合があります。今回は、yumコマンドで、fakesystemdを削除し、systemdをインストールしています。さらに、RUN行の「yum install -y httpd」は、Apache Webサーバーのhttpdパッケージをインストールする記述です。今回使用するDockerイメージは、CentOS 7のsystemdを有効にしますので、RUN行で「systemctl enable httpd」を記述し、コンテナが起動した際に、自動的にApache Webサーバーが起動するようにします。Apache Webサーバーのコンテナが外部に開放するポート番号をEXPOSE行で指定します。Dockerfileを記述したら、Dockerイメージを生成します。

# pwd
/root/apache

# ls -l
合計 4
-rw-r--r--. 1 root root 263 11月  9 17:09 Dockerfile


# docker build -t centos7_apache .

Apache Webサーバー入りのDockerイメージ「centos7_apache」が作成されているかを確認します。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
centos7_apache      latest              ac8e9d882d7e        About a minute ago   381.9 MB
...
...

作成したDockerイメージ「centos7_apache」を使ってDockerコンテナを起動します。今回起動するコンテナ名は、「apache001」としました。

# docker run --name apache001 --privileged -i -t -d -p 80:80 centos7_apache /sbin/init
3db4623293db8c6a2e516ac788bb10fa32a73175c46d08c19a6b441d148b6838

DockerイメージがCentOS 7ベースで、コンテナ内でsystemdを使用する場合は、コンテナの起動オプションに、「--privileged」オプションが必要になります。またコンテナの起動に指定するコマンドは、「/sbin/init」を指定します。コンテナが起動したかを確認します。

# docker ps -a
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS                NAMES
3db4623293db        centos7_apache:latest   "/sbin/init"        15 seconds ago      Up 15 seconds       0.0.0.0:80->80/tcp   apache001

コンテナ「apache001」が起動していることがわかります。ホストマシンからコンテナ「apache001」にログインします。

# nsenter -t $(docker inspect --format '{{.State.Pid}}' apache001) -i -m -n -p -u /bin/bash
[root@3db4623293db /]#

上記のようにログインプロンプトが「[root@3db4623293db /]」になったことで、コンテナにログインできていることがわかります。コンテナにログインできていますので、コンテナ上でApache Webサービスが起動しているかを確認します。

[root@3db4623293db /]# systemctl status httpd

コンテナがhttpdサービスを正常に起動できていることを確認できたら、コンテナに割り振られたIPアドレスをコンテナ上で確認します。

[root@3db4623293db /]# ip a |grep inet
    ...
    inet 172.17.0.26/16 scope global eth0
    ...

コンテナが外部にWebサービスを提供できているかをホストマシンや他のクライアントマシンから確認します。コマンドラインから確認するには、curlコマンドが有用です。

# curl 172.17.0.26/index.html
Hello Apache.

【注意】

本連載では、CentOS 7のDockerイメージにsystemdをインストールする方法を紹介しましたが、Dockerコンテナ上でのsystemdの利用については、全てのアプリケーションやデーモンについて、十分なテストが行われているわけではありません。したがって、利用者の自己責任の元で十分な動作確認を行って上記手順を利用するように下さい。

日本ヒューレット・パッカード株式会社 プリセールス統括本部 ソリューションセンター OSS・Linux担当 シニアITスペシャリスト

兵庫県伊丹市出身。1996年頃からオープンソースに携わる。2000年よりUNIXサーバーのSE及びスーパーコンピューターの並列計算プログラミング講師を担当。科学技術計算サーバーのSI経験も持つ。2005年、大手製造業向けLinuxサーバー提案で日本HP社長賞受賞。2006年、米国HPからLinux技術の伝道師に与えられる「OpenSource and Linux Ambassador Hall of Fame」を2年連続受賞。日本HPプリセールスMVPを4度受賞。現在は、Linux、FreeBSD、Hadoop等のOSSを駆使したスケールアウト型サーバー基盤のプリセールスSE、技術検証、技術文書執筆を担当。日本HPのオープンソース・Linuxテクノロジーエバンジェリストとして講演活動も行っている。Red Hat Certified Engineer、Red Hat Certified Virtualization Administrator、Novell Certified Linux Professional、EXIN Cloud Computing Foundation Certificate、HP Accredited Systems Engineer Cloud Architect、Red Hat Certified System Administrator in Red Hat OpenStack、Cloudera Certified Administrator for Apache Hadoop認定技術者。HP公式ブログ執筆者。趣味はレーシングカートとビリヤード

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています