📘

コンテナで複数プロセスを起動する

2023/05/05に公開

目的

Java(Spring Boot)で作ったRestful WebAPIをNginx経由で呼び出したい。このときnginxとWebAPI(Javaアプリケーション)を1つのコンテナで稼働させるために、supervisorを使って複数プロセスを起動できる構成にする。

supervisord.confの作成

supervisorの設定ファイルを作成する。

  • [supervisord]セクション

    • nodaemon: trueを設定してdaemonで起動しないようにする(フォアグラウンドで動作させる)。
  • [program:xxxxx]セクション

    • command: 実行するコマンドラインを記述する
      今回は、javanginxの2つ
    • stdout_xxx: 標準出力をコンテナログにリダイレクトする
    • stderr_xxx: 標準エラー出力をコンテナログにリダイレクトする
    • autostart: 自動起動を有効化(default : true)
    • autorestart: 自動再起動を有効化(default : unexpected)
[supervisord]
nodaemon=true

[program:java-app]
command=java -Dfile.encoding=UTF-8 -jar /app/<jar file name>.jar
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=10

[program:nginx]
command=nginx -g "daemon off;"
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=5


Dockerfileの作成

Dockerファイルに記述する主な内容は次の通り。

  • nginxをインストールする
  • supervisorをインストールする
  • JDKをコピー&Javaの設定をする
    • 今回はMicrosoft Build of OpenJDKを使用
  • ファイルをコピーする
    • 作成したconfigファイル
    • ビルドしたアプリケーション
FROM ubuntu:20.04

# Install nginx
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
  && apt-get install -y gnupg2 ca-certificates \
  && apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ABF5BD827BD9BF62 \
  && echo "deb https://nginx.org/packages/ubuntu/ focal nginx" >> /etc/apt/sources.list.d/nginx.list \
  && echo "deb-src https://nginx.org/packages/ubuntu/ focal nginx" >> /etc/apt/sources.list.d/nginx.list \
  && apt-get update \
  && apt-get install -y nginx --no-install-recommends

# Install Supervisor
RUN apt-get update \
  && apt-get install -y supervisor \
  && mkdir -p /var/log/supervisor

# Copy JDK
ENV JAVA_HOME /usr/lib/jvm/msopenjdk-17-amd64
ENV PATH "${JAVA_HOME}/bin:${PATH}"
COPY --from=mcr.microsoft.com/openjdk/jdk:17-ubuntu $JAVA_HOME $JAVA_HOME

# Copy .conf
COPY ./nginx/default /etc/nginx/conf.d/default.conf
COPY ./supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Copy Application
RUN mkdir /app
COPY  ./app/<jar file name>.jar /app/<jar file name>.jar

EXPOSE 80

CMD ["supervisord", "-c", "/etc/supervisord.conf"]


Containerの起動をShellにする

ShellFileから起動したい場合は、以下のようにする。

  1. Shellファイルを用意

    #
    # 実行したい処理を記述
    #
    
    # supervisorを起動
    /usr/bin/supervisord
    
  2. Dockerfileをshellを起動するように修正

    #~中略~
    
    # Copy .sh
    COPY ./startup/container_startup.sh container_startup.sh
    
    EXPOSE 80
    
    # CMD ["supervisord", "-c", "/etc/supervisord.conf"]
    CMD ["sh","-c","./container_startup.sh"]
    


JDKのContainerイメージを使用した場合

JDKのディストリビューションのコンテナイメージを使用するとJDKの追加部分が不要になる。

# Use JDK Image
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu

# Install nginx
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
  && apt-get install -y gnupg2 ca-certificates \
  && apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys ABF5BD827BD9BF62 \
  && echo "deb https://nginx.org/packages/ubuntu/ focal nginx" >> /etc/apt/sources.list.d/nginx.list \
  && echo "deb-src https://nginx.org/packages/ubuntu/ focal nginx" >> /etc/apt/sources.list.d/nginx.list \
  && apt-get update \
  && apt-get install -y nginx --no-install-recommends

# Install Supervisor
RUN apt-get update \
  && apt-get install -y supervisor \
  && mkdir -p /var/log/supervisor

# Copy .conf
COPY ./nginx/default /etc/nginx/conf.d/default.conf
COPY ./supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Copy Application
RUN mkdir /app
COPY  ./app/<jar file name>.jar /app/<jar file name>.jar

# Copy .sh
COPY ./startup/container_startup.sh container_startup.sh

EXPOSE 80

CMD ["sh","-c","./container_startup.sh"]

おわりに

Java側の死活監視の要否や1コンテナ・1プロセス論とかはまた別の話。

参考にしたドキュメント

https://docs.docker.com/config/containers/multi-service_container/
http://supervisord.org/configuration.html

Discussion