2023.03.17

dockerでsystemctlコマンドが使えるLinuxを構築する ~m1/m2 macでvagrant/virtualbox代わりの仮想環境を手に入れる~

次世代システム研究室の Y.I です。m1/m2 mac に systemctl や他 Linux コマンドが使える docker コンテナを構築する方法をまとめます。先日 MySQL のハンズオンを実施するために、ローカルPCの m1/m2 mac 上で MySQL がインストールされた Ubuntu コンテナの docker 環境を構築しました。各種 Linux コマンド、特に systemctl コマンドでのサービス起動停止が行える docker image を作成できるので、本番サーバーに近い形で MySQL を構築、設定できてハンズオンの役に立ちました。 m1/m2 mac 使いの方で Linux 操作に慣れるためにも役に立つと思います。仮想環境構築に困っている方や Docker コンテナだけど通常のVMに近い形で使いたい方へ、是非お試しください。



モチベーション

筆者は m1 mac を使って開発を行っています。 m1/m2 mac で困るのが仮想環境構築ではないでしょうか? m1 mac 以降 Vagrant/Virtualbox が使えなくなってしまいました(解決方法あるのでしょうか?)。代わりに docker で開発を進めているのですが、 Linux のアプリケーションの起動停止に使う systemctl コマンドが使えなかったり、提供されている docker image 以上のことをやろうと思うと出来なかったり出来ても苦労した経験があります。そこで今回は以下の環境を構築しました。


完成形

  • m1/m2 mac 上で動作 (Intel Mac でも動作します)
  • docker/docker compose で2台のコンテナを構築
  • systemctl や 各種 Linux コマンドが使える Ubuntu
  • MySQL8 インストール済み/起動済み
  • MySQLデータを永続化する (dockerコンテナを削除してもデータが残り再利用可能)

  • お急ぎの方は、こちらをクリック。 ファイル全文、コマンドをまとめています。

    ※docker-composeについて

    こちらでは、docker composeコマンドとして記載しています。ご自身のdockerバージョンに合わせて読み替えてください。
    docker-compose コマンドは2023年にEOL予定です。エイリアスによりコマンド自体は利用できるとのことです。


    構築手順

    環境構築は、以下3コマンドで完了します。m1 macbook airだと90秒ほどで起動完了しました。

    docker volume create db1vol
    docker volume create db2vol
    
    docker compose up -d --build (or docker-compose up -d --build)
    
  • 永続化
  • コンテナ構築/起動
  • docker/docker compose説明

    Dockerfile

    ベースとなる Ubuntu ベースの docker イメージの作成です。

    # os
    FROM ubuntu:22.04
    
    # tools
    RUN apt-get -y update \
     && apt-get install -y init systemd \
     && apt-get install -y net-tools iputils-ping curl wget telnet less vim sudo \
     && apt-get install -y tzdata locales && locale-gen ja_JP.UTF-8 \
    
    # この1ヶ月で必要とされるようになったので追加
    RUN apt-get install -y lsb-release  gnupg
    
    # JP対応
    ENV TZ Asia/Tokyo
    ENV LANG ja_JP.UTF-8
    ENV LANGUAGE ja_JP:ja
    
  • FROM: OSには執筆時stable latest の Ubuntu 22.04 を指定
  • initd, systemd: systemctlコマンドを使えるようにする
  • net-tools他: Linux 各種コマンドをインストール(筆者がよく使うコマンド)
  • tzdata他, ENV: 日本時間や日本語対応

  • compose.yaml(docker-compose.yaml)

    コンテナdb1

    services:
      db1:
        container_name: db1
        build:
          context: .
          dockerfile: Dockerfile
        privileged: true
        command: /sbin/init
        networks:
          db_net:
            ipv4_address: 192.168.100.11
        ports:
          - "13306:3306"
        volumes:
          - db1vol:/var/lib/mysql
    
  • container_name: コンテナ名を指定しています。省略するとdockerが自動的に名前をつけます。
  • build-dockerfile: コンテナイメージ指定。同じパスにあるDockerfileからイメージを作成します。
  • privileged, command: 権限付与, initd で起動します。これによってsystemctlコマンドが使えるようになります
  •     privileged: true
    

    「Failed to get D-Bus connection: Operation not permitted」対策としてDockerの特権コンテナとして起動します。
    特権コンテナとはホストコンピュータリソースへのアクセスが可能となり脆弱性につながります。そのため、外部からアクセスされない環境でのみ許可するようにしましょう。

  • networks: ipアドレスを固定で割り当てています
  • ports: ホストportとコンテナportのマッピング
  • volumes: mysqlデータを永続化するために docker volume を 割り当てています

  • Network設定

    networks:
      db_net:
        driver: bridge
        ipam:
          config:
          - subnet: 192.168.100.0/24
    
  • ipam-config-subnet: サブネットを指定しています。192.168.100.0 ~ 192.168.100.255
  • 各コンテナの設定にて上記サブネット範囲のIPアドレスを割り当てています

  • 永続化(docker volume)設定

    volumes:
      db1vol:
        external: true
      db2vol:
        external: true
    
  • volumes: volume名として db1vol, db2vol を指定しています
  • external: compose.yamlファイルで管理していないdocker volumeを利用します。 事前に docker volume create コマンドで作成しておきます。

  • MySQL

    Dockerfile

    MySQLのインストールはこちらの設定で可能です. バージョンは執筆時latest 8.0.32 がインストールされます. Dockerfile に追加してください。

    # MySQL8
    RUN curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb
    RUN apt-get install -y ./mysql-apt-config_0.8.24-1_all.deb
    RUN apt-get -y update \
     && apt-get install -y mysql-server
    
    VOLUME /var/lib/mysql
    

    my.cnf

    インストールされる MySQL はリモートホストからのアクセスが制限されている状態で構築されるので、リモートホストからのアクセスが可能に設定します。

    ・/etc/mysql/mysql.conf.d/mysqld.cnf を修正します
    
    下記コメントアウト/#をつけてください
    bind-address            = 127.0.0.1
    mysqlx-bind-address     = 127.0.0.1
    
    ・mysql を再起動して設定を有効化します。
    
    systemctl stop mysql
    systemctl start mysql
    

    以上で m1/m2/intel mac に systemctl で MySQL の起動停止を行える Ubuntu 環境が手に入ります。agt-get も利用できるので、いろいろなパッケージをインストール可能です。



    まとめ

    ご紹介した Dockerfile, compose.yaml 全文と起動コマンドをこちらにまとめておきます。


    – コマンド
    - mysqlデータ永続化
    docker volume create db1vol
    docker volume create db2vol
    
    - コンテナ構築/起動
    docker compose up -d --build
    

    – Dockerfile 全体
    # os
    FROM ubuntu:22.04
    
    # tools
    RUN apt-get -y update \
     && apt-get install -y init systemd \
    # && apt-get install -y systemd \
     && apt-get install -y net-tools iputils-ping curl wget telnet less vim sudo \
     && apt-get install -y tzdata locales && locale-gen ja_JP.UTF-8 \
     && apt-get clean \
     && rm -rf /var/lib/apt/lists/*
    
    # JP対応
    ENV TZ Asia/Tokyo
    ENV LANG ja_JP.UTF-8
    ENV LANGUAGE ja_JP:ja
    
    # MySQL8
    RUN curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.24-1_all.deb
    RUN apt-get install -y ./mysql-apt-config_0.8.24-1_all.deb
    RUN apt-get -y update \
     && apt-get install -y mysql-server
    
    VOLUME /var/lib/mysql
    

    – compose.yaml(docker-compose.yaml) 全体
    version: '3'
    
    services:
      db1:
        container_name: db1
        build:
          context: .
          dockerfile: Dockerfile
        privileged: true
        command: /sbin/init
        networks:
          db_net:
            ipv4_address: 192.168.100.11
        ports:
          - "13306:3306"
        volumes:
          - db1vol:/var/lib/mysql
      db2:
        container_name: db2
        build:
          context: .
          dockerfile: Dockerfile
        privileged: true
        command: /sbin/init
        networks:
          db_net:
            ipv4_address: 192.168.100.12
        ports:
          - "23306:3306"
        volumes:
          - db2vol:/var/lib/mysql
    
    networks:
      db_net:
        driver: bridge
        ipam:
          config:
          - subnet: 192.168.100.0/24
    
    volumes:
      db1vol:
        external: true
      db2vol:
        external: true
    


    最後に

    グループ研究開発本部では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。アプリケーション開発の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。

    • Twitter
    • Facebook
    • はてなブックマークに追加

    グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

     
    • AI研究開発室
    • 大阪研究開発グループ

    関連記事