Dockerfile 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # WyOJ web image.
  2. #
  3. # Build context is the REPOSITORY ROOT (see ../docker-compose.yml):
  4. # docker build -t wyoj-web -f web/Dockerfile .
  5. #
  6. # The context has to be the root because the web image also needs the judger
  7. # tree:
  8. # * uoj_judger/run/formatter -- used by dataSyncProblemData() on the web
  9. # * uoj_judger/include/testlib.h -- served by /download.php
  10. # * judge_client.zip -- served by /judge/download/judger
  11. # ../.dockerignore keeps the database dump and ./uoj_data out of the context.
  12. #
  13. # v8js is needed by app/models/UOJBlogEditor.php (markdown -> HTML), and the
  14. # yaml extension by yaml_parse() in that same file.
  15. #
  16. # NOTE on web/v8js.zip: it is a 397 KB local tarball (upstream phpv8/v8js,
  17. # patched build used in production) and is tracked by git on purpose, so that a
  18. # clean clone builds without network access to github.com. If you would rather
  19. # not track it: add it back to .gitignore and replace the COPY below with
  20. # RUN git clone --depth=1 https://github.com/phpv8/v8js.git /tmp/pear/download/v8js
  21. # (note: `git clone -b <sha>` does not work with a raw commit id).
  22. FROM ubuntu:20.04
  23. LABEL org.opencontainers.image.source=https://git.ryp.org.cn/wyoj/wyoj-raw
  24. LABEL org.opencontainers.image.description="WyOJ Web"
  25. LABEL org.opencontainers.image.licenses=MIT
  26. ENV DEBIAN_FRONTEND=noninteractive
  27. # ---------------------------------------------------------------------------
  28. # System packages
  29. #
  30. # libv8 7.5 only exists in the bionic PPA, hence the mixed release. Importing
  31. # the PPA key from a keyserver is flaky (and keyserver.ubuntu.com may be
  32. # unreachable); if it fails we mark just that one repo trusted so the build
  33. # does not depend on a keyserver being up.
  34. # ---------------------------------------------------------------------------
  35. RUN dpkg -s gnupg >/dev/null 2>&1 || (apt-get update && apt-get install -y gnupg); \
  36. echo "deb http://ppa.launchpad.net/stesie/libv8/ubuntu bionic main" \
  37. > /etc/apt/sources.list.d/stesie-libv8.list; \
  38. if ! apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D858A0DF; then \
  39. echo "WARN: could not import the libv8 PPA key; marking that repo trusted"; \
  40. sed -i 's|^deb |deb [trusted=yes] |' /etc/apt/sources.list.d/stesie-libv8.list; \
  41. fi; \
  42. apt-get update && apt-get install -y \
  43. git vim ntp zip unzip curl wget \
  44. apache2 libapache2-mod-xsendfile libapache2-mod-php \
  45. php php-dev php-pear php-zip php-mysql php-mbstring php-gd php-intl php-xsl \
  46. g++ make re2c libv8-7.5-dev libyaml-dev && \
  47. yes | pecl install yaml && \
  48. rm -rf /var/lib/apt/lists/*
  49. # ---------------------------------------------------------------------------
  50. # v8js + yaml extensions
  51. # ---------------------------------------------------------------------------
  52. COPY web/v8js.zip /tmp/pear/download/
  53. RUN set -eux; \
  54. cd /tmp/pear/download; \
  55. unzip -q v8js.zip; \
  56. cd v8js; \
  57. phpize; \
  58. ./configure --with-php-config=/usr/bin/php-config --with-v8js=/opt/libv8-7.5; \
  59. make -j"$(nproc)"; \
  60. make install; \
  61. cd /; \
  62. rm -rf /tmp/pear/download/v8js
  63. # Enable the extensions for both SAPIs instead of patching php.ini by line
  64. # number (the old `sed -i '912a\...' /etc/php/7.4/apache2/php.ini` broke the
  65. # moment the base image changed).
  66. RUN set -eux; \
  67. for sapi in apache2 cli; do \
  68. printf 'extension=v8js.so\nextension=yaml.so\n' > "/etc/php/7.4/${sapi}/conf.d/20-uoj.ini"; \
  69. done; \
  70. php -m | grep -qx v8js; \
  71. php -m | grep -qx yaml
  72. # ---------------------------------------------------------------------------
  73. # Judger tree
  74. #
  75. # The web needs this too (see the header comment). Only run/formatter is
  76. # actually executed here; the judge clients' self-update zip is built from the
  77. # sources so that they recompile it themselves (judge_client runs
  78. # `make clean && make` after unzipping).
  79. #
  80. # The zip is written to /opt/uoj/judge_client.zip, *not* into app/storage --
  81. # app/storage is a bind mount at runtime and would shadow it. install.sh -i
  82. # copies it into place.
  83. # ---------------------------------------------------------------------------
  84. COPY judger /opt/uoj/judger
  85. RUN set -eux; \
  86. make -C /opt/uoj/judger/uoj_judger run/formatter -j"$(nproc)"; \
  87. cd /opt/uoj/judger; \
  88. zip -q -r -y /opt/uoj/judge_client.zip judge_client uoj_judger \
  89. -x 'uoj_judger/data' 'uoj_judger/data/*' \
  90. 'uoj_judger/work/*' 'uoj_judger/result/*' \
  91. 'uoj_judger/run/formatter' \
  92. 'log/*' '*.o'; \
  93. unzip -l /opt/uoj/judge_client.zip | tail -2
  94. # ---------------------------------------------------------------------------
  95. # Application
  96. #
  97. # ADD comes last so that editing PHP/CSS only invalidates the cheap layers.
  98. # `install.sh -p` prepares apache/php config and the /var/www/uoj symlink; it
  99. # does not touch the database (that happens at container start).
  100. # ---------------------------------------------------------------------------
  101. ADD web /opt/uoj/web
  102. WORKDIR /opt/uoj/web
  103. RUN chmod +x install.sh docker-entrypoint.sh && bash install.sh -p
  104. ENV LANG=C.UTF-8 TZ=Asia/Shanghai
  105. EXPOSE 80
  106. CMD ["/bin/sh", "/opt/uoj/web/docker-entrypoint.sh"]