Skip to content

Commit 925fd19

Browse files
committed
github: rework Docker build, and publish new images
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]>
1 parent d256748 commit 925fd19

File tree

8 files changed

+277
-227
lines changed

8 files changed

+277
-227
lines changed

.github/workflows/docker.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions
2+
name: Build Docker Images
3+
on:
4+
# Manual trigger:
5+
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#workflow_dispatch
6+
workflow_dispatch:
7+
# Scheduled trigger:
8+
# https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events
9+
schedule:
10+
- cron: "0 1 * * mon" # every monday at 1am
11+
12+
env:
13+
# We have to use 'glean' here, not 'Glean', because Docker does not allow
14+
# uppercase letters in image names, so the image push will inevitably fail
15+
BASE_IMAGE_NAME: ${{ github.repository_owner }}/glean
16+
REGISTRY: ghcr.io
17+
18+
jobs:
19+
build-docker:
20+
name: Build and Push Docker Images
21+
strategy:
22+
matrix:
23+
os: [ubuntu-24.04, ubuntu-24.04-arm]
24+
runs-on: ${{ matrix.os }}
25+
permissions:
26+
contents: read
27+
packages: write
28+
steps:
29+
- name: Checkout Repository
30+
uses: actions/checkout@v4
31+
with:
32+
persist-credentials: false
33+
34+
- name: Log in to the Container registry
35+
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
36+
with:
37+
registry: ${{ env.REGISTRY }}
38+
username: ${{ github.actor }}
39+
password: ${{ secrets.GITHUB_TOKEN }}
40+
41+
- name: Derive image tags
42+
run: |
43+
DATE=$(date +%Y%m%d%H%M)
44+
echo "Using date: ${DATE}"
45+
echo "Using hash: ${GITHUB_SHA}"
46+
echo "IMAGE_DATE_TAG=v${DATE}" >> $GITHUB_ENV
47+
echo "IMAGE_SHA_TAG=${GITHUB_SHA}" >> $GITHUB_ENV
48+
env:
49+
GITHUB_SHA: ${{ github.sha }}
50+
51+
- name: Build and save Docker images
52+
run: |
53+
for x in server client demo; do
54+
docker build -t $x:latest --target $x .
55+
for v in latest ${IMAGE_DATE_TAG} ${IMAGE_SHA_TAG}; do
56+
docker tag $x:latest ${REGISTRY}/${BASE_IMAGE_NAME}/$x:$v
57+
done
58+
done
59+
env:
60+
REGISTRY: ${{ env.REGISTRY }}
61+
BASE_IMAGE_NAME: ${{ env.BASE_IMAGE_NAME }}
62+
IMAGE_DATE_TAG: ${{ env.IMAGE_DATE_TAG }}
63+
IMAGE_SHA_TAG: ${{ env.IMAGE_SHA_TAG }}
64+
65+
- name: Test Docker image
66+
run: |
67+
docker run --rm \
68+
--entrypoint /usr/local/bin/glean \
69+
demo:latest \
70+
shell --db-root /glean/db --schema dir:/glean/schema \
71+
':describe' \
72+
':db react/0' \
73+
':stat'
74+
75+
- name: Push image to the Container registry
76+
run: |
77+
set -x
78+
for x in server client demo; do
79+
for v in latest ${IMAGE_DATE_TAG} ${IMAGE_SHA_TAG}; do
80+
echo docker push $x:latest ${REGISTRY}/${BASE_IMAGE_NAME}/$x:$v
81+
done
82+
done
83+
env:
84+
REGISTRY: ${{ env.REGISTRY }}
85+
BASE_IMAGE_NAME: ${{ env.BASE_IMAGE_NAME }}
86+
IMAGE_DATE_TAG: ${{ env.IMAGE_DATE_TAG }}
87+
IMAGE_SHA_TAG: ${{ env.IMAGE_SHA_TAG }}

.github/workflows/glean-docker.yml

Lines changed: 0 additions & 43 deletions
This file was deleted.

Dockerfile

Lines changed: 131 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,146 @@
1-
FROM ghcr.io/facebookincubator/hsthrift/ci-base:latest as tools
2-
# remove any old stuff
3-
RUN rm -rf /usr/local/lib
4-
RUN rm -rf /usr/local/include
5-
RUN apt-get install -y ghc-8.10.2 cmake ninja-build libxxhash-dev wget unzip rsync libgmock-dev
6-
RUN cabal update
7-
RUN mkdir /glean-code
8-
WORKDIR /glean-code
9-
ADD https://api.github.com/repos/facebookincubator/hsthrift/compare/main...HEAD /dev/null
10-
ADD ./glean /glean-code/glean
11-
ADD ./thrift /glean-code/thrift
12-
ADD ./cabal.project /glean-code/
13-
ADD ./Makefile /glean-code/
14-
ADD ./mk /glean-code/mk
15-
ADD ./glean.cabal.in /glean-code/
16-
ADD ./LICENSE /glean-code/
17-
ADD ./Setup.hs /glean-code/
18-
ADD ./install_deps.sh /glean-code/
19-
RUN ./install_deps.sh
20-
# Nuke build artifacts to save space
21-
RUN rm -rf /tmp/fbcode_builder_getdeps-Z__wZGleanZGleanZhsthriftZbuildZfbcode_builder-root/
1+
# MARK: build: deps+setup
2+
FROM ubuntu:24.04 AS build
3+
WORKDIR /build
224

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

27-
RUN make
28-
RUN cp $(cabal exec --project-file=cabal.project -- which glean) ~/.cabal/bin/
29-
RUN cp $(cabal exec --project-file=cabal.project -- which glean-server) ~/.cabal/bin/
30-
RUN cp $(cabal exec --project-file=cabal.project -- which glean-hyperlink) ~/.cabal/bin/
31-
RUN glean --help
32-
RUN wget https://github.com/facebook/flow/releases/download/v0.219.0/flow-linux64-v0.219.0.zip
33-
RUN unzip flow-linux64-v0.219.0.zip
34-
RUN mkdir -p /root/.hsthrift/bin && mv flow/flow /root/.hsthrift/bin/ && rm -rf flow-linux64-v0.219.0.zip flow/
35-
WORKDIR /
36-
RUN git clone https://github.com/facebook/react.git --depth 1 react-code
37-
RUN cat /react-code/scripts/flow/config/flowconfig \
38-
| grep -v REACT_RENDERER_FLOW_ \
39-
| grep -v CI_MAX_WORKERS \
40-
| grep -v FLOW_VERSION \
41-
| sed '/^\[options\]/a exact_by_default=false' > /react-code/.flowconfig
15+
# Install base dependencies.
16+
RUN apt update \
17+
&& apt install -y \
18+
curl locales build-essential clang-$CLANG_VER git ninja-build make cmake libboost-all-dev \
19+
libgmp-dev libaio-dev libbz2-dev libdouble-conversion-dev libdwarf-dev libgoogle-glog-dev libiberty-dev libjemalloc-dev \
20+
libnuma-dev liblzma-dev liblz4-dev libsnappy-dev libsodium-dev libssl-dev libunwind-dev libzstd-dev libfast-float-dev \
21+
pkg-config rsync libgmock-dev libpcre3-dev libtinfo-dev libxxhash-dev patchelf \
22+
&& locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8
23+
24+
# Install GHC and Cabal via ghcup.
25+
RUN curl --proto '=https' --tlsv1.2 -sSf "https://downloads.haskell.org/~ghcup/$(uname -m)-linux-ghcup" -o /tmp/ghcup \
26+
&& chmod +x /tmp/ghcup \
27+
&& /tmp/ghcup install cabal $CABAL_VER --set \
28+
&& /tmp/ghcup install ghc $GHC_VER --set
4229

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

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

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

50-
RUN apt-get update && apt-get install -y \
51-
libicu66 \
52-
libboost-context1.71.0 \
53-
libboost-filesystem1.71.0 \
54-
libboost-program-options1.71.0 \
55-
libboost-regex1.71.0 \
56-
libunwind8 \
57-
libgoogle-glog0v5 \
58-
libssl1.1 \
59-
libsodium23 \
60-
libdouble-conversion3 \
61-
libmysqlclient21 \
62-
libevent-2.1-7 \
63-
libsnappy-dev \
64-
libxxhash0 \
65-
libatomic1 \
66-
&& apt-get clean && rm -rf /var/lib/apt/lists/*
64+
# MARK: common: base image
65+
FROM ubuntu:24.04 AS common
66+
# This image only exists so that the client and server images can share it.
67+
COPY --from=build /build/bindir/lib/* /usr/local/lib
68+
RUN mkdir -p /glean/db /glean/schema \
69+
&& apt update \
70+
&& apt install -y \
71+
libatomic1 \
72+
libsnappy1v5 \
73+
libpcre3 \
74+
libunwind8 \
75+
libgoogle-glog0v6t64 \
76+
libicu74 \
77+
libdouble-conversion3 \
78+
libevent-2.1-7t64 \
79+
libdwarf1 \
80+
libsodium23 \
81+
libaio1t64 \
82+
libboost-context1.83.0 \
83+
libboost-regex1.83.0 \
84+
libboost-program-options1.83.0 \
85+
libboost-system1.83.0 \
86+
libboost-thread1.83.0 \
87+
libboost-atomic1.83.0 \
88+
libboost-filesystem1.83.0
6789

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

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

72-
COPY --from=tools /root/.hsthrift/lib /usr/local/lib
73-
COPY --from=tools /root/.hsthrift/bin/flow /usr/local/bin
74-
COPY --from=tools /root/.cabal/bin/glean /glean-demo/bin
75-
COPY --from=tools /root/.cabal/bin/glean-server /glean-demo/bin
76-
COPY --from=tools /root/.cabal/bin/glean-hyperlink /glean-demo/bin
77-
COPY --from=tools /glean-code/glean/schema /glean-demo/schema
78-
COPY --from=tools /react-code /glean-demo/code
79-
ADD docker_entrypoint.sh docker_entrypoint.sh
99+
FROM common AS tools
100+
COPY --from=build /build/bindir/bin/glean /usr/local/bin
101+
COPY --from=build /build/bindir/bin/gen-schema /usr/local/bin/glean-gen-schema
80102

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

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

90-
ENV REPO_NAME=react
118+
FROM server AS demo
119+
COPY --from=build /build/bindir/bin/glean-hyperlink /usr/local/bin
120+
COPY --from=build /build/glean/schema/source /glean/schema/
121+
COPY --from=demo-build /tmp/flow/flow /usr/local/bin
122+
COPY --from=demo-build /react-code /glean/code/react
91123

92-
EXPOSE 8888
124+
WORKDIR /glean
125+
RUN mkdir -p /tmp/flow-index-out \
126+
&& flow glean code/react --output-dir /tmp/flow-index-out --write-root "" \
127+
&& glean --db-root db --schema dir:schema create --repo react/0 \
128+
&& glean --db-root db --schema dir:schema write --repo react/0 /tmp/flow-index-out/* \
129+
&& glean --db-root db --schema dir:schema derive --repo react/0 flow.FileXRef flow.FileDeclaration \
130+
&& glean --db-root db --schema dir:schema finish --repo react/0 \
131+
&& rm -rf /tmp/flow-index-out
93132

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

96-
# docker run -ti -p8888:8888 ghcr.io/facebookincubator/glean/demo
144+
EXPOSE 8888
145+
EXPOSE 12345
146+
ENTRYPOINT ["/usr/local/bin/glean-demo"]

Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,18 @@ cxx-libraries:
132132
cxx-test-%: force
133133
@$(MAKE) -f mk/cxx.mk --no-print-directory CXX_MODE=$(CXX_MODE) CXX_DIR=$(CXX_DIR) $@
134134

135+
GLEAN_CABAL_BINS=glean glean-server glean-hyperlink gen-schema
136+
GLEAN_NATIVE_LIBS=librocksdb.so.8 libfolly.so.0.58.0-dev libfmt.so.11
135137
.PHONY: glean
136138
glean:: glean.cabal cxx-libraries
137-
$(CABAL) build glean glean-server glean-hyperlink
139+
$(CABAL) build $(GLEAN_CABAL_BINS)
140+
141+
CABAL_BUILD_PREFIX := dist-newstyle/build/$(shell uname -m)-linux/ghc-$(shell ghc --numeric-version)/glean-0.1.0.0/x
142+
.PHONY: bindist
143+
bindist: glean
144+
for b in $(GLEAN_CABAL_BINS); do install -D $(CABAL_BUILD_PREFIX)/$$b/build/$$b/$$b bindir/bin/$$b; done
145+
for l in $(GLEAN_NATIVE_LIBS); do install -D $(HOME)/.hsthrift/lib/$$l bindir/lib/$$l; done
146+
strip bindir/bin/* bindir/lib/*
138147

139148
.PHONY: gen-bytecode
140149
gen-bytecode: $(BYTECODE_GEN)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[![CI](https://github.com/facebookincubator/Glean/actions/workflows/ci.yml/badge.svg)](https://github.com/facebookincubator/Glean/actions/workflows/ci.yml)
2-
[![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)
2+
[![Glean demo Docker image](https://github.com/facebookincubator/Glean/actions/workflows/docker.yml/badge.svg)](https://github.com/facebookincubator/Glean/actions/workflows/docker.yml)
33

44
# Glean
55

0 commit comments

Comments
 (0)