Skip to content

Commit

Permalink
github: rework Docker build, and publish new images
Browse files Browse the repository at this point in the history
This reworks the `Dockerfile` to now build multiple images, including
one for end users to run their own copy of Glean, and an updated version
of the React demo database. It includes x86_64 and aarch64 Linux images
using public GHA runners, which probably covers 98% of all realistic
uses. (Using GHA runners means this workflow is trivially usable for
public forks, too.)

There is a new `bindist` target used by the Dockerfile that creates a
directory of needed binaries and libraries, and properly packages them
for usage in the container.

There are now three containers published from the `Dockerfile`, all
based on Ubuntu 24.04:

- `glean/client`, which only contains the `glean` command, then
- `glean/server`, including `glean-server`, then
- `glean/demo`, including a precanned `glean-hyperlink` + react DB

These containers are all size-optimized; the final images have no
development tools installed and the absolute minimum necessary installed
packages. For example, the new x86_64 `glean/demo` is only 486MB
uncompressed, compared to the 2.4GB of the previous demo version. The
`client` and `server` images are 251MB and 300MB, respectively.

The `client` image should probably include `gen-schema` so that end
users can generate code from their own non-upstream `.angle` files, but
that can be added in a future patch.

In theory, this new container could also be used to replace most of the
junk in `ci.yml` in order to repeat ourselves less, but it would need
another image in order to add more things so that the test suite can be
run. That can happen in a future patch.

Signed-off-by: Austin Seipp <[email protected]>
  • Loading branch information
thoughtpolice committed Jan 24, 2025
1 parent c637787 commit 6623245
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 227 deletions.
87 changes: 87 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions
name: Build Docker Images
on:
# Manual trigger:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch
workflow_dispatch:
# Scheduled trigger:
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events
schedule:
- cron: "0 1 * * mon" # every monday at 1am

env:
# We have to use 'glean' here, not 'Glean', because Docker does not allow
# uppercase letters in image names, so the image push will inevitably fail
BASE_IMAGE_NAME: ${{ github.repository_owner }}/glean
REGISTRY: ghcr.io

jobs:
build-docker:
name: Build and Push Docker Images
strategy:
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
runs-on: ${{ matrix.os }}
permissions:
contents: read
packages: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Log in to the Container registry
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Derive image tags
run: |
DATE=$(date +%Y%m%d%H%M)
echo "Using date: ${DATE}"
echo "Using hash: ${GITHUB_SHA}"
echo "IMAGE_DATE_TAG=${DATE}" >> $GITHUB_ENV
echo "IMAGE_SHA_TAG=${GITHUB_SHA}" >> $GITHUB_ENV
env:
GITHUB_SHA: ${{ github.sha }}

- name: Build and save Docker images
run: |
for x in server client demo; do
docker build -t $x:latest --target $x .
for v in latest ${IMAGE_DATE_TAG} ${IMAGE_SHA_TAG}; do
docker tag $x:latest ${REGISTRY}/${BASE_IMAGE_NAME}/$x:$v
done
done
env:
REGISTRY: ${{ env.REGISTRY }}
BASE_IMAGE_NAME: ${{ env.BASE_IMAGE_NAME }}
IMAGE_DATE_TAG: ${{ env.IMAGE_DATE_TAG }}
IMAGE_SHA_TAG: ${{ env.IMAGE_SHA_TAG }}

- name: Test Docker image
run: |
docker run -it --rm \
--entrypoint /usr/local/bin/glean \
demo:latest \
shell --db-root /glean/db --schema dir:/glean/schema \
':describe' \
':db react/0' \
':stat'
- name: Push image to the Container registry
run: |
set -x
for x in server client demo; do
for v in latest ${IMAGE_DATE_TAG} ${IMAGE_SHA_TAG}; do
echo docker push $x:latest ${REGISTRY}/${BASE_IMAGE_NAME}/$x:$v
done
done
env:
REGISTRY: ${{ env.REGISTRY }}
BASE_IMAGE_NAME: ${{ env.BASE_IMAGE_NAME }}
IMAGE_DATE_TAG: ${{ env.IMAGE_DATE_TAG }}
IMAGE_SHA_TAG: ${{ env.IMAGE_SHA_TAG }}
43 changes: 0 additions & 43 deletions .github/workflows/glean-docker.yml

This file was deleted.

212 changes: 131 additions & 81 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,96 +1,146 @@
FROM ghcr.io/facebookincubator/hsthrift/ci-base:latest as tools
# remove any old stuff
RUN rm -rf /usr/local/lib
RUN rm -rf /usr/local/include
RUN apt-get install -y ghc-8.10.2 cmake ninja-build libxxhash-dev wget unzip rsync libgmock-dev
RUN cabal update
RUN mkdir /glean-code
WORKDIR /glean-code
ADD https://api.github.com/repos/facebookincubator/hsthrift/compare/main...HEAD /dev/null
ADD ./glean /glean-code/glean
ADD ./thrift /glean-code/thrift
ADD ./cabal.project /glean-code/
ADD ./Makefile /glean-code/
ADD ./mk /glean-code/mk
ADD ./glean.cabal.in /glean-code/
ADD ./LICENSE /glean-code/
ADD ./Setup.hs /glean-code/
ADD ./install_deps.sh /glean-code/
RUN ./install_deps.sh
# Nuke build artifacts to save space
RUN rm -rf /tmp/fbcode_builder_getdeps-Z__wZGleanZGleanZhsthriftZbuildZfbcode_builder-root/
# MARK: build: deps+setup
FROM ubuntu:24.04 AS build
WORKDIR /build

ENV LD_LIBRARY_PATH=/root/.hsthrift/lib
ENV PKG_CONFIG_PATH=/root/.hsthrift/lib/pkgconfig
ENV PATH=$PATH:/root/.hsthrift/bin
# This is what is tested at Meta, so we use it here.
ENV GHC_VER=9.2.8
# See: https://github.com/haskell/cabal/issues/10046
ENV CABAL_VER=3.10
# Major available version of Clang.
ENV CLANG_VER=15
# Must be set for GHC, otherwise cabal will fail to build files with non-ASCII
# characters (like lens).
ENV LANG=en_US.UTF-8

RUN make
RUN cp $(cabal exec --project-file=cabal.project -- which glean) ~/.cabal/bin/
RUN cp $(cabal exec --project-file=cabal.project -- which glean-server) ~/.cabal/bin/
RUN cp $(cabal exec --project-file=cabal.project -- which glean-hyperlink) ~/.cabal/bin/
RUN glean --help
RUN wget https://github.com/facebook/flow/releases/download/v0.219.0/flow-linux64-v0.219.0.zip
RUN unzip flow-linux64-v0.219.0.zip
RUN mkdir -p /root/.hsthrift/bin && mv flow/flow /root/.hsthrift/bin/ && rm -rf flow-linux64-v0.219.0.zip flow/
WORKDIR /
RUN git clone https://github.com/facebook/react.git --depth 1 react-code
RUN cat /react-code/scripts/flow/config/flowconfig \
| grep -v REACT_RENDERER_FLOW_ \
| grep -v CI_MAX_WORKERS \
| grep -v FLOW_VERSION \
| sed '/^\[options\]/a exact_by_default=false' > /react-code/.flowconfig
# Install base dependencies.
RUN apt update \
&& apt install -y \
curl locales build-essential clang-$CLANG_VER git ninja-build make cmake libboost-all-dev \
libgmp-dev libaio-dev libbz2-dev libdouble-conversion-dev libdwarf-dev libgoogle-glog-dev libiberty-dev libjemalloc-dev \
libnuma-dev liblzma-dev liblz4-dev libsnappy-dev libsodium-dev libssl-dev libunwind-dev libzstd-dev libfast-float-dev \
pkg-config rsync libgmock-dev libpcre3-dev libtinfo-dev libxxhash-dev patchelf \
&& locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8

# Install GHC and Cabal via ghcup.
RUN curl --proto '=https' --tlsv1.2 -sSf "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" -o /tmp/ghcup \
&& chmod +x /tmp/ghcup \
&& /tmp/ghcup install cabal $CABAL_VER --set \
&& /tmp/ghcup install ghc $GHC_VER --set

FROM ubuntu:20.04 AS demo
# Use Clang, not gcc. Note that this MUST happen *AFTER* installing GHC above.
# Apparently `ghcup` presumably modifies the settings for GHC in some way, which
# inevitably causes a link failure due to incompatible -fPIC vs non-fPIC build
# settings...
RUN apt remove -y gcc g++ && apt autoremove -y \
&& update-alternatives --install /usr/bin/cc cc /usr/bin/clang-$CLANG_VER 10 \
&& update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-$CLANG_VER 10 \
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/clang-$CLANG_VER 10 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/clang++-$CLANG_VER 10

LABEL org.opencontainers.image.source="https://github.com/facebookincubator/Glean"
# Run deps build (rocksdb, folly, hsthrift, etc). install_deps.sh needs some of
# the source files, so copy the minimum amount needed so that we can skip this
# step as much as possible (because these files are not changed) as frequently.)
COPY ./mk ./mk
COPY install_deps.sh Makefile cabal.project glean.cabal.in ./
RUN ./install_deps.sh --threads $(nproc)
RUN rm -rf /tmp/fbcode_builder_getdeps-Z__wZGleanZGleanZhsthriftZbuildZfbcode_builder-root/

ENV PATH=/glean-demo/bin:$PATH
ENV LD_LIBRARY_PATH=/usr/local/lib
# MARK: build: main build
COPY ./thrift/ ./thrift
COPY ./glean ./glean
RUN touch settings.mk \
&& echo "EXTRA_GHC_OPTS=-j$(nproc) +RTS -A128m -n2m -RTS" >> settings.mk \
&& echo "CABAL_CONFIG_FLAGS=-fclang -f-hack-tests -f-rust-tests -f-python-tests" >> settings.mk
RUN true && \
( export LD_LIBRARY_PATH=$HOME/.hsthrift/lib:$LD_LIBRARY_PATH \
; export PKG_CONFIG_PATH=$HOME/.hsthrift/lib/pkgconfig:$PKG_CONFIG_PATH \
; export PATH=$HOME/.ghcup/bin:$HOME/.hsthrift/bin:$PATH \
; cabal update && make -j$(nproc) && make bindist \
)
# Now patch the binaries to include /usr/local/lib in their rpath, as that's
# where the final libraries will go anyway.
RUN patchelf --add-rpath /usr/local/lib ./bindir/bin/*

RUN apt-get update && apt-get install -y \
libicu66 \
libboost-context1.71.0 \
libboost-filesystem1.71.0 \
libboost-program-options1.71.0 \
libboost-regex1.71.0 \
libunwind8 \
libgoogle-glog0v5 \
libssl1.1 \
libsodium23 \
libdouble-conversion3 \
libmysqlclient21 \
libevent-2.1-7 \
libsnappy-dev \
libxxhash0 \
libatomic1 \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# MARK: common: base image
FROM ubuntu:24.04 AS common
# This image only exists so that the client and server images can share it.
COPY --from=build /build/bindir/lib/* /usr/local/lib
RUN mkdir -p /glean/db /glean/schema \
&& apt update \
&& apt install -y \
libatomic1 \
libsnappy1v5 \
libpcre3 \
libunwind8 \
libgoogle-glog0v6t64 \
libicu74 \
libdouble-conversion3 \
libevent-2.1-7t64 \
libdwarf1 \
libsodium23 \
libaio1t64 \
libboost-context1.83.0 \
libboost-regex1.83.0 \
libboost-program-options1.83.0 \
libboost-system1.83.0 \
libboost-thread1.83.0 \
libboost-atomic1.83.0 \
libboost-filesystem1.83.0

WORKDIR /glean-demo
# MARK: server+client
FROM common AS client
COPY --from=build /build/bindir/bin/glean /usr/local/bin
CMD ["/usr/local/bin/glean", "--schema", "dir:/glean/schema"]

RUN mkdir /glean-demo/bin
FROM client AS server
COPY --from=build /build/bindir/bin/glean-server /usr/local/bin
CMD ["/usr/local/bin/glean-server", "--db-root", "/glean/db", "--schema", "dir:/glean/schema", "--port", "12345"]

COPY --from=tools /root/.hsthrift/lib /usr/local/lib
COPY --from=tools /root/.hsthrift/bin/flow /usr/local/bin
COPY --from=tools /root/.cabal/bin/glean /glean-demo/bin
COPY --from=tools /root/.cabal/bin/glean-server /glean-demo/bin
COPY --from=tools /root/.cabal/bin/glean-hyperlink /glean-demo/bin
COPY --from=tools /glean-code/glean/schema /glean-demo/schema
COPY --from=tools /react-code /glean-demo/code
ADD docker_entrypoint.sh docker_entrypoint.sh
FROM common AS tools
COPY --from=build /build/bindir/bin/glean /usr/local/bin
COPY --from=build /build/bindir/bin/gen-schema /usr/local/bin/glean-gen-schema

RUN mkdir -p db /tmp/flow-index-out
# MARK: demo setup
FROM common AS demo-build
RUN apt update && apt install -y unzip git
ADD https://github.com/facebook/flow/releases/download/v0.245.2/flow-linux64-v0.245.2.zip /tmp/flow-x86_64.zip
ADD https://github.com/facebook/flow/releases/download/v0.245.2/flow-linux-arm64-v0.245.2.zip /tmp/flow-aarch64.zip
RUN true && (cd /tmp; unzip flow-$(uname -m).zip)

RUN flow glean code --output-dir /tmp/flow-index-out --write-root "" && \
glean --db-root db --schema dir:schema/source create --repo react/0 && \
glean --db-root db --schema dir:schema/source write --repo react/0 /tmp/flow-index-out/* && \
glean --db-root db --schema dir:schema/source derive --repo react/0 flow.FileXRef flow.FileDeclaration && \
glean --db-root db --schema dir:schema/source finish --repo react/0 && \
rm -Rf /tmp/flow-index-out
RUN true \
&& git clone --depth 1 --branch v19.0.0 https://github.com/facebook/react.git /react-code \
&& rm -rf /react-code/.git
RUN cat /react-code/scripts/flow/config/flowconfig \
| grep -v REACT_RENDERER_FLOW_ \
| grep -v FLOW_VERSION \
| sed '/^\[options\]/a exact_by_default=false' > /react-code/.flowconfig

ENV REPO_NAME=react
FROM server AS demo
COPY --from=build /build/bindir/bin/glean-hyperlink /usr/local/bin
COPY --from=build /build/glean/schema/source /glean/schema/
COPY --from=demo-build /tmp/flow/flow /usr/local/bin
COPY --from=demo-build /react-code /glean/code/react

EXPOSE 8888
WORKDIR /glean
RUN mkdir -p /tmp/flow-index-out \
&& flow glean code/react --output-dir /tmp/flow-index-out --write-root "" \
&& glean --db-root db --schema dir:schema create --repo react/0 \
&& glean --db-root db --schema dir:schema write --repo react/0 /tmp/flow-index-out/* \
&& glean --db-root db --schema dir:schema derive --repo react/0 flow.FileXRef flow.FileDeclaration \
&& glean --db-root db --schema dir:schema finish --repo react/0 \
&& rm -rf /tmp/flow-index-out

ENTRYPOINT ["./docker_entrypoint.sh"]
# write out a simple inline script to start the demo app
RUN touch /usr/local/bin/glean-demo \
&& chmod a+x /usr/local/bin/glean-demo \
&& echo "#!/usr/bin/env bash" >> /usr/local/bin/glean-demo \
&& echo "set -ex" >> /usr/local/bin/glean-demo \
&& echo "/usr/local/bin/glean-server --db-root /glean/db --schema dir:/glean/schema --port 12345 &" >> /usr/local/bin/glean-demo \
&& echo "sleep 3" >> /usr/local/bin/glean-demo \
&& echo "exec /usr/local/bin/glean-hyperlink --service localhost:12345 --repo react --root /glean/code/react --http 8888" >> /usr/local/bin/glean-demo \
# Add a dummy favicon.ico so that the web server doesn't complain. \
&& touch /glean/code/react/favicon.ico

# docker run -ti -p8888:8888 ghcr.io/facebookincubator/glean/demo
EXPOSE 8888
EXPOSE 12345
ENTRYPOINT ["/usr/local/bin/glean-demo"]
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,18 @@ cxx-libraries:
cxx-test-%: force
@$(MAKE) -f mk/cxx.mk --no-print-directory CXX_MODE=$(CXX_MODE) CXX_DIR=$(CXX_DIR) $@

GLEAN_CABAL_BINS=glean glean-server glean-hyperlink gen-schema
GLEAN_NATIVE_LIBS=librocksdb.so.8 libfolly.so.0.58.0-dev libfmt.so.11
.PHONY: glean
glean:: glean.cabal cxx-libraries
$(CABAL) build glean glean-server glean-hyperlink
$(CABAL) build $(GLEAN_CABAL_BINS)

CABAL_BUILD_PREFIX := dist-newstyle/build/$(shell uname -m)-linux/ghc-$(shell ghc --numeric-version)/glean-0.1.0.0/x
.PHONY: bindist
bindist: glean
for b in $(GLEAN_CABAL_BINS); do install -D $(CABAL_BUILD_PREFIX)/$$b/build/$$b/$$b bindir/bin/$$b; done
for l in $(GLEAN_NATIVE_LIBS); do install -D $(HOME)/.hsthrift/lib/$$l bindir/lib/$$l; done
strip bindir/bin/* bindir/lib/*

.PHONY: gen-bytecode
gen-bytecode: $(BYTECODE_GEN)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![CI](https://github.com/facebookincubator/Glean/actions/workflows/ci.yml/badge.svg)](https://github.com/facebookincubator/Glean/actions/workflows/ci.yml)
[![Glean demo Docker image](https://github.com/facebookincubator/Glean/actions/workflows/glean-docker.yml/badge.svg)](https://github.com/facebookincubator/Glean/actions/workflows/glean-docker.yml)
[![Glean demo Docker image](https://github.com/facebookincubator/Glean/actions/workflows/docker.yml/badge.svg)](https://github.com/facebookincubator/Glean/actions/workflows/docker.yml)

# Glean

Expand Down
Loading

0 comments on commit 6623245

Please sign in to comment.