diff --git a/.dockerignore b/.dockerignore new file mode 120000 index 00000000000..6200b3ae7d8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +./.gitignore \ No newline at end of file diff --git a/.gitignore b/.gitignore index 306d402c326..42a64d2003b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ npm-debug.log yarn-error.log testem.log .env +docker-compose.override.yml diff --git a/backend.Dockerfile b/backend.Dockerfile new file mode 100644 index 00000000000..14dfe75e37d --- /dev/null +++ b/backend.Dockerfile @@ -0,0 +1,11 @@ +FROM rust:1.20-stretch + +RUN apt-get update \ + && apt-get install -y postgresql cmake \ + && rm -rf /var/lib/apt/lists/* \ + && cargo install diesel_cli --no-default-features --features postgres + +WORKDIR /app +COPY . /app + +ENTRYPOINT ["/app/docker_entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000000..7f20997973b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +version: "3" +services: + postgres: + image: postgres:9.6 + environment: + POSTGRES_DB: cargo_registry + POSTRES_USER: postgres + POSTGRES_PASSWORD: password + ports: + - 5432:5432 + volumes: + - postgres-data:/var/lib/postgresql/data + backend: + build: + context: . + dockerfile: backend.Dockerfile + environment: + DATABASE_URL: postgres://postgres:password@postgres/cargo_registry + SESSION_KEY: badkeyabcdefghijklmnopqrstuvwxyzabcdef + GIT_REPO_URL: file://./tmp/index-bare + GIT_REPO_CHECKOUT: ./tmp/index-co + GH_CLIENT_ID: "" + GH_CLIENT_SECRET: "" + links: + - postgres + ports: + - 8888:8888 + volumes: + # Mount the src/ directory so we don't have to rebuild the Docker image + # when we want to change some code + - ./src:/app/src:ro + + - index:/app/tmp + - cargo-cache:/usr/local/cargo/registry + - target-cache:/app/target + frontend: + build: + context: . + dockerfile: frontend.Dockerfile + entrypoint: yarn run start --proxy http://backend:8888 + links: + - backend + ports: + - 4200:4200 + volumes: + # Mount the app/ directory so live reload works + - ./app:/app/app:ro + +volumes: + postgres-data: + cargo-cache: + target-cache: + index: diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh new file mode 100755 index 00000000000..20a2b068233 --- /dev/null +++ b/docker_entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# If the backend is started before postgres is ready, the migrations will fail +until diesel migration run; do + echo "Migrations failed, retrying in 5 seconds..." + sleep 5 +done + +./script/init-local-index.sh + +cargo run --bin server diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 45411db99ba..337304fbcae 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -472,3 +472,90 @@ this crate's `Cargo.toml`, and `cargo build` should display output like this: Compiling thiscrate v0.1.0 (file:///path/to/thiscrate) Finished dev [unoptimized + debuginfo] target(s) in 0.56 secs ``` + +### Running crates.io with Docker + +There are Dockerfiles to build both the backend and the frontend, +(`backend.Dockerfile` and `frontend.Dockerfile`) respectively, but it is most +useful to just use docker-compose to bring up everything that's needed all in +one go: + +``` +docker-compose up -d +``` + +The Compose file is filled out with a sane set of defaults that should Just +Work™ out of the box without any modification. Individual settings can be +overridden by creating a `docker-compose.override.yml` with the updated config. +For example, in order to specify a set of Github OAuth Client credentials, a +`docker-compose.override.yml` file might look like this: + +```yaml +version: "3" +services: + backend: + environment: + GH_CLIENT_ID: blahblah_ID + GH_CLIENT_SECRET: blahblah_secret +``` + +#### Accessing services + +By default, the services will be exposed on their normal ports: + +* `5432` for Postgres +* `8888` for the crates.io backend +* `4200` for the crates.io frontend + +These can be changed with the `docker-compose.override.yml` file. + +#### Publishing crates + +Unlike a local setup, the Git index is not stored in the `./tmp` folder, so in +order to publish to the Dockerized crates.io, run + +``` +cargo publish --index http://localhost:4200/git/index +``` + +#### Changing code + +The `app/` directory is mounted directly into the frontend Docker container, +which means that the Ember live-reload server will still just work. If +anything outside of `app/` is changed, the base Docker image will have to be +rebuilt: + +```sh +# Rebuild frontend Docker image +docker-compose build frontend + +# Restart running frontend container (if it's already running) +docker-compose stop frontend +docker-compose rm frontend +docker-compose up -d +``` + +Similarly, the `src/` directory is mounted into the backend Docker container, +so in order to recompile the backend, run: + +``` +docker-compose restart backend +``` + +If anything outside of `src/` is changed, the base Docker image will have to be +rebuilt: + +```sh +# Rebuild backend Docker image +docker-compose build backend + +# Restart running backend container (if it's already running) +docker-compose stop backend +docker-compose rm backend +docker-compose up -d +``` + +#### Volumes + +A number of names volumes are created, as can be seen in the `volumes` section +of the `docker-compose.yml` file. diff --git a/frontend.Dockerfile b/frontend.Dockerfile new file mode 100644 index 00000000000..47706fc9de3 --- /dev/null +++ b/frontend.Dockerfile @@ -0,0 +1,10 @@ +FROM node:8.6-alpine + +WORKDIR /app +COPY package.json /app + +RUN yarn install + +COPY . /app + +ENTRYPOINT ["yarn", "run", "start:staging"]