Red Hat Satelliteを使わずに、１台でRHEL7/6,CentOS7/6のリポジトリサーバをつくる

# はじめに
直接インターネットに接続できない、RHEL7/6,CentOS7/6のサーバ達の為に、リポジトリサーバを立てたいと思ったのが事の発端になります。

単純なリポジトリサーバではなく、各種管理機能が含まれたソフトとして以下のようなものもあるが、今回はそこまでは求めていないので却下しました。

- RHELの製品として、Red Hat Satellite。
- Red Hat Satellite 5 のオープンソースとしてSpacewalk。
- Red Hat Satellite 6 のオープンソースとしてKatello,Foreman,Pulp,Candlepin。

CentOSはrsyncで同期するやり方があったが、RHELはrsyncでは無理そうなのと、環境的に外部にWEB(HTTP/HTTPS）アクセスしか許可されていなかったので断念しました。

以下のRed Hatのサイトにreposyncの記述があったので実現性を検討してみると、yumのツールの一種なのでWEBアクセスでリポジトリが作成できることがわかったので、この方式を採用しました。

+ Satellite サーバーを使用せずに、Red Hat Enterprise Linux 5、6、または 7 の最新アップデートのローカルミラーを作成する。(https://access.redhat.com/ja/solutions/472533)

次に、dockerのコンテナでもyumが使えることから、コンテナを使えば１台で複数OSのリポジトリ作れるのではないかと調べてみると、以下のRed Hatのサイトを発見。ホストに割り当てたサブスクリプションに紐づくリポジトリがコンテナでも利用できるということで、この方式も採用しました。

+ Enabling repositories inside a Docker-formatted container image and utilizing Red Hat subscriptions or entitlements to access repositories   (https://access.redhat.com/solutions/1443553)

# システム構成・概要
## システム構成  

+ ホストOS：RHEL 7.6
+ コンテナ型仮想化：docker 1.13.1
+ WEBサーバ：Apache 2.4.6
+ コンテナイ１：RHEL 7.6-252
+ コンテナイ２：RHEL 6.10-514
+ コンテナイ３：CentOS 6.10
+ コンテナイ４：CentOS 7.6.1810

## システム概要  

コンテナで外部リポジトリと同期して出力するフォルダとして、ホスト側のApacheのドキュメントルートをマウントすることで、そのままリポジトリとして公開できるようにします。

![リポジトリイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129763/41aa239d-e4d1-d593-968f-7ee64e02e9ef.png)

# 構築手順

## ホスト(RHEL7)のインストール
まずは、ホストとしてRHEL7のインストール、システム登録を行います。

- OSインストール
RHEL7.6を最小構成でインストールします。

- Red Hatの諸条件に同意
最初にRed Hatの諸条件に同意しておかないと後続の作業が進められないため、以下のサイトにアクセスし承諾します。  
https://www.redhat.com/wapps/tnc/ackrequired?site=candlepin&event=signOn

- RHSMでシステムの登録

```
# subscription-manager register
登録中: subscription.rhsm.redhat.com:443/subscription
ユーザー名: XXXXXXXX
パスワード:
このシステムは、次の ID で登録されました: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
登録したシステム名: XXXXXXXX

# subscription-manager list
<省略>
状態:             サブスクライブなし
状態の詳細:       有効なサブスクリプションでサポートされていません。
<省略>

# subscription-manager list --available
<省略>
プール ID:                XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<省略>

# subscription-manager attach --pool=XXXXXXXXXXXXXXXXXXXXXXX
サブスクリプションが正しく割り当てられました: Red Hat Developer Subscription

# subscription-manager list
<省略>
状態:             サブスクライブ済み
状態の詳細:
<省略>
```

## dockerの構築
- extrasリポジトリ追加  
dockerはextrasリポジトリにあるので、リポジトリを追加します。

```
# subscription-manager repos --enable rhel-7-server-extras-rpms
リポジトリー 'rhel-7-server-extras-rpms' は、このシステムに対して有効になりました。
```

- OSの最新化  
OSを最新の状態にアップデートし、カーネルアップデートなどもあるので念のため再起動します。

```
# yum update -y
# shutdown -r now
```

- SELINUXを無効

```
# vi /etc/sysconfig/selinux
･･･
SELINUX=disabled
･･･
# setenforce 0
```

- firewalldを無効  
dockerでiptablesが使用されるため、firewlldを停止・無効化します。

```
# systemctl stop firewalld
# systemctl disable firewalld
```

- iptablesを有効  
dockerでiptablesが使用されるため、インストール、起動、有効化します。

``` 
# yum install iptables-services -y
# systemctl start iptables
# systemctl enable iptables
```

- dockerインストール  
dockerのインストール、起動、有効化をします。

```
# yum install docker -y
# systemctl start docker
# systemctl enable docker
```

- Apacheのインストール  
Apacheのインストール、起動、有効化をします。

```
# yum install httpd -y
# systemctl start httpd
# systemctl enable httpd
# vi /etc/sysconfig/iptables
```
以下の通り、80番ポートへのアクセスを許可します。

```
# sample configuration for iptables service
# you can edit this manually or use system-config-firewall
# please do not ask us to add additional ports/services to this default configuration
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
```

- 再起動  
一通りインストール・設定できたので再起動します。

```
# shutdown -r now
```

## RHELのコンテナの取得
https://access.redhat.com/containers/
こちらからコンテナイメージの情報を検索し、取得(pull)します。

```
# docker pull registry.access.redhat.com/rhel7:7.6-252
# docker pull registry.access.redhat.com/rhel6:6.10-514
```

## CentOSのコンテナの取得  
https://hub.docker.com/
こちらからコンテナイメージの情報を検索し、取得(pull)します。

```
# docker pull centos:7.6.1810
# docker pull centos:6.10
```

## dockerイメージの確認
取得したイメージの確認します。

```
# docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
registry.access.redhat.com/rhel7   7.6-252             5044f6040ea5        9 days ago          203 MB
registry.access.redhat.com/rhel6   6.10-514            c3d7822f2e85        3 weeks ago         200 MB
docker.io/centos                   6.10                48650444e419        6 weeks ago         194 MB
docker.io/centos                   7.6.1810            f1cb7c7d58b7        6 weeks ago         202 MB
```

## イメージの名前・タグ名を修正
個人的な意見ですが、微妙にイメージの名前・タグが分かりにくいので別名・タグをつけます。

```
# docker tag registry.access.redhat.com/rhel7:7.6-252 rhel7:7.6-252
# docker tag registry.access.redhat.com/rhel6:6.10-514 rhel6:6.10-514
# docker tag docker.io/centos:6.10 centos6:6.10
# docker tag docker.io/centos:7.6.1810 centos7:7.6.1810
# docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
registry.access.redhat.com/rhel7   7.6-252             5044f6040ea5        9 days ago          203 MB
rhel7                              7.6-252             5044f6040ea5        9 days ago          203 MB
rhel6                              6.10-514            c3d7822f2e85        3 weeks ago         200 MB
registry.access.redhat.com/rhel6   6.10-514            c3d7822f2e85        3 weeks ago         200 MB
centos6                            6.10                48650444e419        6 weeks ago         194 MB
docker.io/centos                   6.10                48650444e419        6 weeks ago         194 MB
centos7                            7.6.1810            f1cb7c7d58b7        6 weeks ago         202 MB
docker.io/centos                   7.6.1810            f1cb7c7d58b7        6 weeks ago         202 MB
```

## rhel6のリポジトリ作成

+ rhel6のコンテナ起動  
rhel6のイメージからコンテナを作成・実行・接続します。その際に、ホストの/var/www/htmlをコンテナンにマウントします。

```
# docker run -i -t -v /var/www/html:/var/www/html --name rhel6repo rhel6:6.10-514 /bin/bash
```

ここ以降、コンテナ内からのコマンド実行になります。

試しにsubscription-managerを実行してみると、コンテナでは無効だからホスト側を参照しろと言われます。

```
# subscription-manager list
subscription-manager is disabled when running inside a container. Please refer to your host system for subscription management.
```

リポジトリのファイルを確認してみると、まだ空の状態です。

```
# cat /etc/yum.repos.d/redhat.repo 

#
# Certificate-Based Repositories
# Managed by (rhsm) subscription-manager
#
# *** This file is auto-generated.  Changes made here will be over-written. ***
# *** Use "subscription-manager repo-override --help" if you wish to make changes. ***
#
# If this file is empty and this system is subscribed consider
# a "yum repolist" to refresh available repos
#
```

リポジトリの一覧を取得してファイルを更新・確認してみると、以下のように使えるリポジトリの情報で更新されます。

```
# yum repolist all

# cat /etc/yum.repos.d/redhat.repo 
<省略>
[rhel-6-server-rpms]
<省略>
baseurl = https://cdn.redhat.com/content/dist/rhel/server/6/$releasever/$basearch/os
<省略>
[rhel-6-server-extras-rpms]
<省略>
baseurl = https://cdn.redhat.com/content/dist/rhel/server/6/6Server/$basearch/extras/os
<省略>
```

reposyncが含まれるyum-utilsとcreaterepoのパッケージをインストールします。

```
# yum install -y yum-utils createrepo
```

今回は一例としてrhel-6-server-extras-rpmsのリポジトリを作成します。
実際は、必要なリポジトリだけ同様のことを行います。
ローカルにリポジトリを作成するにあたり、URL・フォルダは似ている方が分かりやすいので、先ほど確認したリポジトリのbaseurlに合わせて作ります。

まずはフォルダを作成し、reposyncで同期します。
-nは最新のもののみで、-nがないと古いバージョンも含めて同期されます。
--norepopathを指定しないと、-pで指定したフォルダの下に、--repoid=で指定した名前のフォルダが作成され、その下に同期されてしまいます。
同期後に、リポジトリのデータを作成するために、createrepoを実行します。

```

# mkdir -p /var/www/html/rhel/server/6/6Server/x86_64/extras/os
# reposync --repoid=rhel-6-server-extras-rpms -n -p /var/www/html/rhel/server/6/6Server/x86_64/extras/os --norepopath --download-metadata
# createrepo /var/www/html/rhel/server/6/6Server/x86_64/extras/os
```

CTRL+P,CTRL+Qでコンテナから抜けます。同期は終わっているので、exitでコンテナを終了させても大丈夫です。

ドキュメントルートの下に作成しているので、この時点でWEBサーバで公開されています。クライアント側のyumの設定を行えば完了です。

## rhel7のリポジトリも同様に作成

```
# docker run -i -t -v /var/www/html:/var/www/html --name rhel7repo rhel7:7.6-252 /bin/bash
# yum repolist all
# cat /etc/yum.repos.d/redhat.repo 
<省略>
[rhel-7-server-extras-rpms]
<省略>
baseurl = https://cdn.redhat.com/content/dist/rhel/server/7/7Server/$basearch/extras/os
<省略>
# yum install -y yum-utils createrepo
# mkdir -p /var/www/html/rhel/server/7/7Server/x86_64/extras/os
# reposync --repoid=rhel-7-server-extras-rpms -n -p /var/www/html/rhel/server/7/7Server/x86_64/extras/os --norepopath --download-metadata
# createrepo /var/www/html/rhel/server/7/7Server/x86_64/extras/os
```

CTRL+P,CTRL+Qでコンテナから抜ける。

## CentOS6のリポジトリの作成
RHELからyum repolist allの手順を削除したものになります。

```
# docker run -i -t -v /var/www/html:/var/www/html --name centos6repo centos6:6.10 /bin/bash
# cat /etc/yum.repos.d/CentOS-Base.repo
<省略>
[centosplus]
<省略>
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
<省略>
# yum install -y yum-utils createrepo
# mkdir -p /var/www/html/centos/6/centosplus/x86_64
# reposync --repoid=centosplus -n -p /var/www/html/centos/6/centosplus/x86_64 --norepopath --download-metadata
```

CTRL+P,CTRL+Qでコンテナから抜ける。

## CentOS7のリポジトリの作成
CentOS6と同様の手順になります。

```
# docker run -i -t -v /var/www/html:/var/www/html --name centos7repo centos7:7.6.1810 /bin/bash
# cat /etc/yum.repos.d/CentOS-Base.repo
<省略>
[centosplus]
<省略>
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
<省略>
# yum install -y yum-utils createrepo
# mkdir -p /var/www/html/centos/7/centosplus/x86_64
# reposync --repoid=centosplus -n -p /var/www/html/centos/7/centosplus/x86_64 --norepopath --download-metadata
# createrepo /var/www/html/centos/7/centosplus/x86_64
```

CTRL+P,CTRL+Qでコンテナから抜ける。

# 最後に
同期しているリポジトリはあくまで例です。実際は、rhel-6-server-rpms,rhel-7-server-rpms,base等々も必要になるので、適宜修正してください。
同期に使用する通信はWEBアクセスなので、PROXY環境下でも動作します。適宜docker,yumにPROXYの設定をしてください。

# この記事に関して
この記事が提供している情報に関しては、合法性、正確性、安全性等、いかなる保証もされません。この記事を利用することによって生ずるいかなる損害に対しても一切責任を負いません。