Skip to content

Commit

Permalink
Run separate web server, registry watcher and build servers in docker…
Browse files Browse the repository at this point in the history
…-compose
  • Loading branch information
Nemo157 committed Nov 15, 2023
1 parent ad94784 commit 17b0ef0
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 113 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Build the Docker image
run: docker build -t docs-rs -f dockerfiles/Dockerfile .
- run: docker build --target web-server -f dockerfiles/Dockerfile .
- run: docker build --target build-server -f dockerfiles/Dockerfile .
- run: docker build --target registry-watcher -f dockerfiles/Dockerfile .
- run: docker build --target cli -f dockerfiles/Dockerfile .
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/ignored
/.env
/.docker.env
/src/web/badge/Cargo.lock
target
*.css
Expand Down
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ mkdir -p ignored/cratesfyi-prefix/crates.io-index
# Builds the docs.rs binary
cargo build
# Start the external services.
docker compose up -d db s3
docker compose up --wait db s3
# anything that doesn't run via docker-compose needs the settings defined in
# .env. Either via `. ./.env` as below, or via any dotenv shell integration.
. ./.env
Expand Down Expand Up @@ -106,14 +106,18 @@ which uses docker-compose for the web server as well.
This will not cache dependencies - in particular, you'll have to rebuild all 400 whenever the lockfile changes -
but makes sure that you're in a known environment so you should have fewer problems getting started.

You can also use the `web` container to run builds on systems which don't support running builds directly (mostly on Mac OS or Windows):
You'll need to `touch .docker.env` first, this file can have any environment
variable overrides you want to use in docker containers.

You can also use the `cli` container to run builds on systems which don't support running builds directly (mostly on Mac OS or Windows):

```sh
# run a build for a single crate
docker compose run web build crate regex 1.3.1
docker compose run --rm cli build crate regex 1.3.1
# or build essential files
docker compose run web build add-essential-files
# rebuild the web container when you changed code.
docker compose up -d web --build
docker compose run --rm cli build add-essential-files
# rebuild containers when you changed code.
docker compose up --wait --build
```

You can also run other commands like the setup above from within the container:
Expand Down Expand Up @@ -142,7 +146,7 @@ Three services are defined:

#### Rebuilding Containers

To rebuild the site, run `docker compose build`.
To rebuild the site, run `docker compose --profile all build`.
Note that docker-compose caches the build even if you change the source code,
so this will be necessary anytime you make changes.

Expand All @@ -163,7 +167,7 @@ This is probably because you have `git.autocrlf` set to true,

##### I see the error `/opt/rustwide/cargo-home/bin/cargo: cannot execute binary file: Exec format error` when running builds.

You are most likely not on a Linux platform. Running builds directly is only supported on `x86_64-unknown-linux-gnu`. On other platforms you can use the `docker compose run web build [...]` workaround described above.
You are most likely not on a Linux platform. Running builds directly is only supported on `x86_64-unknown-linux-gnu`. On other platforms you can use the `docker compose run --rm cli build [...]` workaround described above.

See [rustwide#41](https://github.com/rust-lang/rustwide/issues/41) for more details about supporting more platforms directly.

Expand Down Expand Up @@ -191,11 +195,11 @@ cargo run -- start-web-server
```sh
# Builds <CRATE_NAME> <CRATE_VERSION> and adds it into database
# This is the main command to build and add a documentation into docs.rs.
# For example, `docker compose run web build crate regex 1.1.6`
# For example, `docker compose run --rm cli build crate regex 1.1.6`
cargo run -- build crate <CRATE_NAME> <CRATE_VERSION>

# alternatively, via the web container
docker compose run web build crate <CRATE_NAME> <CRATE_VERSION>
# alternatively, within docker-compose containers
docker compose run --rm cli build crate <CRATE_NAME> <CRATE_VERSION>

# Builds every crate on crates.io and adds them into database
# (beware: this may take months to finish)
Expand Down
146 changes: 108 additions & 38 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,119 @@
version: "3"
version: "3.4"

x-healthcheck: &healthcheck-interval
interval: 10s
timeout: 1s
start_period: 10s
# TODO: https://github.com/docker/compose/issues/10461
# start_interval: 1s

x-environment: &environment
RUST_BACKTRACE: true

DOCSRS_PREFIX: /opt/docsrs/prefix

DOCSRS_DATABASE_URL: postgresql://cratesfyi:password@db
DOCSRS_MIN_POOL_SIZE: 2
DOCSRS_MAX_POOL_SIZE: 10

DOCSRS_STORAGE_BACKEND: s3

S3_ENDPOINT: http://s3:9000
AWS_ACCESS_KEY_ID: cratesfyi
AWS_SECRET_ACCESS_KEY: secret_key

DOCSRS_RENDER_THREADS: 2

DOCSRS_RUSTWIDE_WORKSPACE: /opt/docsrs/rustwide
DOCSRS_DOCKER: true
DOCSRS_DOCKER_IMAGE: ghcr.io/rust-lang/crates-build-env/linux-micro
DOCSRS_BUILD_CPU_LIMIT: 2
DOCSRS_INCLUDE_DEFAULT_TARGETS: false

x-builder: &builder
build:
context: .
dockerfile: ./dockerfiles/Dockerfile
target: build-server
depends_on:
- db
- s3
environment: *environment
env_file:
- .docker.env
healthcheck:
<< : *healthcheck-interval
test: curl --silent --fail localhost:3000/about/metrics

services:
web:
build:
context: .
dockerfile: ./dockerfiles/Dockerfile
target: web-server
platform: "linux/amd64"
depends_on:
- db
- s3
ports:
- "3000:3000"
# for metrics
expose: ["3000"]
- "3000:80"
environment: *environment
env_file:
- .docker.env
healthcheck:
<< : *healthcheck-interval
test: curl --silent --fail localhost:80/about/metrics

# Include the registry watcher with `docker compose --profile watch up -d`
registry-watcher:
build:
context: .
dockerfile: ./dockerfiles/Dockerfile
target: registry-watcher
platform: "linux/amd64"
depends_on:
- db
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- ".rustwide-docker:/opt/docsrs/rustwide"
- "cratesio-index:/opt/docsrs/prefix/crates.io-index"
environment:
DOCSRS_RUSTWIDE_WORKSPACE: /opt/docsrs/rustwide
DOCSRS_DATABASE_URL: postgresql://cratesfyi:password@db
DOCSRS_STORAGE_BACKEND: s3
S3_ENDPOINT: http://s3:9000
AWS_ACCESS_KEY_ID: cratesfyi
AWS_SECRET_ACCESS_KEY: secret_key
environment: *environment
env_file:
- .env
- .docker.env
profiles:
- watch
- all
healthcheck:
test: ["CMD", "curl", "--silent", "--fail", "localhost:3000"]
interval: 10s
timeout: 5s
retries: 10
<< : *healthcheck-interval
test: curl --silent --fail localhost:3000/about/metrics

builder-a:
<< : *builder
volumes:
- ".rustwide-docker/builder-a:/opt/docsrs/rustwide"
- "/var/run/docker.sock:/var/run/docker.sock"

builder-b:
<< : *builder
volumes:
- ".rustwide-docker/builder-b:/opt/docsrs/rustwide"
- "/var/run/docker.sock:/var/run/docker.sock"

cli:
build:
context: .
dockerfile: ./dockerfiles/Dockerfile
target: cli
depends_on:
- db
- s3
volumes:
- ".rustwide-docker/cli:/opt/docsrs/rustwide"
- "cratesio-index:/opt/docsrs/prefix/crates.io-index"
- "/var/run/docker.sock:/var/run/docker.sock"
environment: *environment
env_file:
- .docker.env
profiles:
- all

db:
build:
Expand All @@ -44,10 +128,8 @@ services:
# Use a non-standard port on the host to avoid conflicting with existing postgres servers
- "127.0.0.1:15432:5432"
healthcheck:
test: ["CMD", "pg_isready", "--username", "cratesfyi"]
interval: 10s
timeout: 5s
retries: 10
<< : *healthcheck-interval
test: pg_isready --username cratesfyi

s3:
image: minio/minio
Expand All @@ -65,17 +147,8 @@ services:
MINIO_ROOT_USER: cratesfyi
MINIO_ROOT_PASSWORD: secret_key
healthcheck:
test:
[
"CMD",
"curl",
"--silent",
"--fail",
"localhost:9000/minio/health/ready",
]
interval: 10s
timeout: 5s
retries: 10
<< : *healthcheck-interval
test: curl --silent --fail localhost:9000/minio/health/ready

prometheus:
build:
Expand All @@ -84,11 +157,8 @@ services:
ports:
- "127.0.0.1:9090:9090"
healthcheck:
test:
["CMD", "curl", "--silent", "--fail", "localhost:9090/-/ready"]
interval: 10s
timeout: 5s
retries: 10
<< : *healthcheck-interval
test: promtool check healthy

volumes:
postgres-data: {}
Expand Down
87 changes: 63 additions & 24 deletions dockerfiles/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,42 +65,81 @@ RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
ca-certificates \
curl \
tini \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /srv/docsrs

# Tini is a small init binary to properly handle signals
CMD ["/usr/bin/tini", "/usr/local/bin/cratesfyi", "start-web-server", "0.0.0.0:80"]

COPY --from=build /build/target/release/cratesfyi /usr/local/bin
COPY static /srv/docsrs/static
COPY templates /srv/docsrs/templates
COPY vendor /srv/docsrs/vendor

WORKDIR /srv/docsrs
########################
# Build server stage #
########################

FROM ubuntu:22.04 AS build-server

RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
ca-certificates \
tini \
curl \
docker.io \
build-essential \
gcc \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*

# Tini is a small init binary to properly handle signals
CMD ["/usr/bin/tini", "/usr/local/bin/cratesfyi", "start-web-server", "0.0.0.0:80"]
CMD ["/usr/bin/tini", "/usr/local/bin/cratesfyi", "start-build-server"]

COPY --from=build /build/target/release/cratesfyi /usr/local/bin

##################
# Output stage #
##################
############################
# Registry watcher stage #
############################

FROM ubuntu:22.04 AS output
FROM ubuntu:22.04 AS registry-watcher

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
git \
libmagic1 \
docker.io \
ca-certificates \
build-essential \
gcc \
pkg-config \
libssl-dev
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
ca-certificates \
tini \
curl \
git \
&& rm -rf /var/lib/apt/lists/*

# Tini is a small init binary to properly handle signals
CMD ["/usr/bin/tini", "/usr/local/bin/cratesfyi", "start-registry-watcher", "--repository-stats-updater=enabled", "--cdn-invalidator=enabled"]

COPY --from=build /build/target/release/cratesfyi /usr/local/bin

###############
# CLI stage #
###############

FROM ubuntu:22.04 AS cli

RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y \
ca-certificates \
docker.io \
build-essential \
gcc \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir -p /opt/docsrs/prefix
ENTRYPOINT ["/usr/bin/tini", "/usr/local/bin/cratesfyi"]

COPY --from=build /build/target/release/cratesfyi /usr/local/bin
COPY static /opt/docsrs/static
COPY templates /opt/docsrs/templates
COPY dockerfiles/entrypoint.sh /opt/docsrs/
COPY vendor /opt/docsrs/vendor

WORKDIR /opt/docsrs
ENTRYPOINT ["/opt/docsrs/entrypoint.sh"]
CMD ["daemon", "--registry-watcher=disabled"]

0 comments on commit 17b0ef0

Please sign in to comment.