diff --git a/grpc/Dockerfile b/grpc/Dockerfile new file mode 100644 index 0000000..f912313 --- /dev/null +++ b/grpc/Dockerfile @@ -0,0 +1,71 @@ +FROM ubuntu:20.04 AS grpc_build +WORKDIR /root + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ + pkg-config \ + build-essential \ + autoconf \ + libtool \ + cmake \ + libssl-dev \ + git \ + zlib1g \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +# Compile and install gRPC library +WORKDIR /root +RUN git clone -b v1.32.0 --depth 1 --single-branch --recursive https://github.com/grpc/grpc + +WORKDIR /root/grpc +RUN mkdir -p cmake/build + +WORKDIR /root/grpc/cmake/build +RUN cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_BUILD_TYPE=Release \ + -DgRPC_INSTALL=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DgRPC_BUILD_TESTS=OFF \ + -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF \ + -DgRPC_SSL_PROVIDER=package \ + -DgRPC_ZLIB_PROVIDER=package \ + ../../ + +# Use DESTDIR to allow a directory copy between images that leave +# symlinks intact whilst not copying unrelated files from the image +RUN DESTDIR=/root/grpc/INSTALLROOT make -j$(nproc --all) install + +# Cleanup install base +WORKDIR /root/grpc/INSTALLROOT/ +RUN find usr/lib -name *.a -type f -prune -exec rm -rf {} \; + + + +FROM ubuntu:20.04 +WORKDIR /root + +RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ + inotify-tools \ + rsync \ + && rm -rf /var/lib/apt/lists/* + +# Copy grpc/protobuf dependencies +COPY --from=grpc_build /root/grpc/INSTALLROOT/ / + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh + +COPY watch.sh /usr/local/bin/watch.sh +RUN chmod a+x /usr/local/bin/watch.sh + +COPY compile.sh /usr/local/bin/compile.sh +RUN chmod a+x /usr/local/bin/compile.sh + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/grpc/compile.sh b/grpc/compile.sh new file mode 100644 index 0000000..7232492 --- /dev/null +++ b/grpc/compile.sh @@ -0,0 +1,37 @@ +#!/bin/sh +set -e + +INPUT_DIRECTORY="" +OUTPUT_DIRECTORY="" +ROOT_NS_DIRECTORY="" + +print_help() { + echo "Usage: $0 -i INPUT_DIRECTORY -o OUTPUT_DIRECTORY [-n ROOT_NS_DIRECTORY]" + exit 2 +} + +while getopts "i:o:n:" c; do + case $c in + i) INPUT_DIRECTORY=$OPTARG ;; + o) OUTPUT_DIRECTORY=$OPTARG ;; + n) ROOT_NS_DIRECTORY=$OPTARG ;; + *) print_help ;; + esac +done + +# Generate temp path for file generation +TMP_OUTPUT_DIRECTORY=$(mktemp -d) + +# Generate files +find "$INPUT_DIRECTORY" -name "*.proto" -type f -prune -printf 'Building %p\n' -exec protoc \ + --proto_path="$INPUT_DIRECTORY" \ + --php_out="$TMP_OUTPUT_DIRECTORY" \ + --grpc_out="$TMP_OUTPUT_DIRECTORY" \ + --plugin=protoc-gen-grpc=/usr/bin/grpc_php_plugin \ + {} \; + +# Relocate files, accounting for root namespace +rsync -a "$TMP_OUTPUT_DIRECTORY/$ROOT_NS_DIRECTORY" "$OUTPUT_DIRECTORY" + +# Delete any temp files left behind +rm -rf "$TMP_OUTPUT_DIRECTORY" diff --git a/grpc/entrypoint.sh b/grpc/entrypoint.sh new file mode 100644 index 0000000..13eb65c --- /dev/null +++ b/grpc/entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/sh +set -e + +WATCHER_PID="" +WATCH=0 + +print_help() { + echo "Usage: $0 [-w]" + exit 2 +} + +while getopts "w" c; do + case $c in + w) WATCH=1 ;; + *) print_help ;; + esac +done + +if [ $WATCH -eq 1 ]; then + # If watching, start the watch process and listen for term signals + term_handler() { + if [ "$WATCHER_PID" != "" ]; then + kill -TERM "$WATCHER_PID" + fi + } + + trap term_handler TERM + + bash -l -c "/usr/local/bin/watch.sh -i \"$INPUT_DIRECTORY\" -o \"$OUTPUT_DIRECTORY\" -n \"$ROOT_NS_DIRECTORY\"" & WATCHER_PID=$! + wait "$WATCHER_PID" +else + # If not watching, run a compile once directly + /usr/local/bin/compile.sh -i "$INPUT_DIRECTORY" -o "$OUTPUT_DIRECTORY" -n "$ROOT_NS_DIRECTORY" +fi diff --git a/grpc/watch.sh b/grpc/watch.sh new file mode 100644 index 0000000..2cbe8b8 --- /dev/null +++ b/grpc/watch.sh @@ -0,0 +1,42 @@ +#!/bin/sh +set -e + +VERBOSE=0 +if [ "$VERBOSE" = "true" ]; then + VERBOSE=1 +fi + +INPUT_DIRECTORY="" +OUTPUT_DIRECTORY="" +ROOT_NS_DIRECTORY="" + +print_help() { + echo "Usage: $0 -i INPUT_DIRECTORY -o OUTPUT_DIRECTORY [-n ROOT_NS_DIRECTORY]" + exit 2 +} + +while getopts "i:o:n:" c; do + case $c in + i) INPUT_DIRECTORY=$OPTARG ;; + o) OUTPUT_DIRECTORY=$OPTARG ;; + n) ROOT_NS_DIRECTORY=$OPTARG ;; + *) print_help ;; + esac +done + +echo "Watch directory: $INPUT_DIRECTORY" +echo "Build directory: $OUTPUT_DIRECTORY" +echo "Root directory: $ROOT_NS_DIRECTORY" + +# First time compile +/usr/local/bin/compile.sh -i "$INPUT_DIRECTORY" -o "$OUTPUT_DIRECTORY" -n "$ROOT_NS_DIRECTORY" + +# Then watch for changes +inotifywait -q -m -e modify -e attrib -e move -e create -e delete -e delete_self -e unmount "$INPUT_DIRECTORY" | +while read -r directory events filename; do + if [ $VERBOSE -eq 1 ]; then + echo "directory: $directory, events: $events, filename: $filename"; + fi + + /usr/local/bin/compile.sh -i "$INPUT_DIRECTORY" -o "$OUTPUT_DIRECTORY" -n "$ROOT_NS_DIRECTORY" +done diff --git a/php/Dockerfile b/php/Dockerfile index 8cc0d04..087e430 100644 --- a/php/Dockerfile +++ b/php/Dockerfile @@ -1,4 +1,55 @@ -FROM ubuntu:20.04 AS build +FROM ubuntu:20.04 AS grpc_build +WORKDIR /root + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ + pkg-config \ + build-essential \ + autoconf \ + libtool \ + cmake \ + libssl-dev \ + git \ + zlib1g \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +# Compile and install gRPC library +WORKDIR /root +RUN git clone -b v1.32.0 --depth 1 --single-branch --recursive https://github.com/grpc/grpc + +WORKDIR /root/grpc +RUN mkdir -p cmake/build + +WORKDIR /root/grpc/cmake/build +RUN cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_BUILD_TYPE=Release \ + -DgRPC_INSTALL=ON \ + -DBUILD_SHARED_LIBS=ON \ + -DgRPC_BUILD_TESTS=OFF \ + -DgRPC_BUILD_GRPC_CSHARP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF \ + -DgRPC_SSL_PROVIDER=package \ + -DgRPC_ZLIB_PROVIDER=package \ + ../../ + +# Use DESTDIR to allow a directory copy between images that leave +# symlinks intact whilst not copying unrelated files from the image +RUN DESTDIR=/root/grpc/INSTALLROOT make -j$(nproc --all) install + +# Cleanup install base +WORKDIR /root/grpc/INSTALLROOT/ +RUN find usr/lib -name *.a -type f -prune -exec rm -rf {} \; +RUN find usr/lib -name pkgconfig -type d -prune -exec rm -rf {} \; +RUN find usr/lib -name cmake -type d -prune -exec rm -rf {} \; + + +FROM ubuntu:20.04 AS php_build WORKDIR /root ENV DEBIAN_FRONTEND noninteractive @@ -21,7 +72,6 @@ RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ re2c \ curl \ libcurl4-openssl-dev \ - autoconf \ libxml2 \ libxml2-dev \ libonig5 \ @@ -42,6 +92,7 @@ RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ libc-client2007e-dev \ libzip5 \ libzip-dev \ + git \ && rm -rf /var/lib/apt/lists/* ADD https://www.php.net/distributions/php-7.4.5.tar.gz /root/ @@ -93,7 +144,8 @@ RUN ./configure \ --enable-soap=shared \ --with-zip=shared \ --with-kerberos=shared \ - --enable-posix=shared + --enable-posix=shared \ + --with-pear RUN make -j$(nproc --all) RUN make install @@ -102,6 +154,43 @@ RUN cp php.ini-production /etc/php/php.ini RUN mv /etc/php/php-fpm.conf.default /etc/php/php-fpm.conf RUN rm -f /etc/php/php-fpm.d/* RUN rm -f /usr/lib/php/extensions/*/*.a +RUN mkdir -p /etc/php/conf.d + +RUN for ext in /usr/lib/php/extensions/*/*.so ; do filename=$(echo ${ext##*/}| cut -d'.' -f 1) ; \ + echo "extension=$filename" >> "/etc/php/conf.d/00-$filename.ini" ; done && \ + mv "/etc/php/conf.d/00-mysqlnd.ini" "/etc/php/conf.d/01-mysqlnd.ini" && \ + mv "/etc/php/conf.d/00-pdo_mysql.ini" "/etc/php/conf.d/02-pdo_mysql.ini" && \ + sed -i -e 's/extension/zend_extension/' /etc/php/conf.d/00-opcache.ini + +# Copy grpc/protobuf dependencies +COPY --from=grpc_build /root/grpc/INSTALLROOT/ / + +# Compile and install gRPC library +WORKDIR /root +RUN git clone -b v1.32.0 --depth 1 --single-branch --recursive https://github.com/grpc/grpc + +# Compile and install the grpc php extension +WORKDIR /root/grpc/src/php/ext/grpc +RUN phpize +RUN ./configure +RUN make +RUN make install + +WORKDIR /root +RUN git clone -b v3.13.0 --depth 1 --single-branch --recursive https://github.com/protocolbuffers/protobuf.git + +# Compile and install the protobuf php extension +WORKDIR /root/protobuf/php/ext/google/protobuf + +RUN phpize +RUN ./configure +RUN php make-preload.php +RUN make +RUN make install + +# register grpc & protobuf extensions with php +RUN echo "extension=grpc" >> "/etc/php/conf.d/00-grpc.ini" +RUN echo "extension=protobuf" >> "/etc/php/conf.d/00-protobuf.ini" FROM ubuntu:20.04 @@ -122,18 +211,15 @@ RUN apt update && DEBIAN_FRONTEND=noninteractive apt install -y \ RUN mkdir -p /etc/php/ RUN mkdir -p /usr/lib/php/extensions -RUN mkdir -p /etc/php/conf.d -COPY --from=build /usr/bin/php /usr/bin/ -COPY --from=build /usr/sbin/php-fpm /usr/sbin/ -COPY --from=build /etc/php /etc/php -COPY --from=build /usr/lib/php/extensions/ /usr/lib/php/extensions +COPY --from=php_build /usr/bin/php /usr/bin/ +COPY --from=php_build /usr/sbin/php-fpm /usr/sbin/ +COPY --from=php_build /etc/php /etc/php +COPY --from=php_build /usr/lib/php/extensions/ /usr/lib/php/extensions -RUN for ext in /usr/lib/php/extensions/*/*.so ; do filename=$(echo ${ext##*/}| cut -d'.' -f 1) ; \ - echo "extension=$filename" >> "/etc/php/conf.d/00-$filename.ini" ; done && \ - mv "/etc/php/conf.d/00-mysqlnd.ini" "/etc/php/conf.d/01-mysqlnd.ini" && \ - mv "/etc/php/conf.d/00-pdo_mysql.ini" "/etc/php/conf.d/02-pdo_mysql.ini" && \ - sed -i -e 's/extension/zend_extension/' /etc/php/conf.d/00-opcache.ini +# Copy grpc/protobuf dependencies +COPY --from=grpc_build /root/grpc/INSTALLROOT/usr/lib/ /usr/lib/ +COPY --from=grpc_build /root/grpc/INSTALLROOT/usr/share/grpc/roots.pem /usr/share/grpc/roots.pem # Create phpfpm user/group RUN groupadd -g 82 php