Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General comment: Rocket Dockerfile with Alpine latest, Rust nightly, rustup #1322

Closed
joelparkerhenderson opened this issue Jun 1, 2020 · 15 comments

Comments

@joelparkerhenderson
Copy link

Here's my first attempt at a Rocket Dockerfile with Alpine latest, Rust nightly, rustup, and related dependencies.

I am sharing it here to help others, and also to seek feedback on how to do it better. Because Rocket needs nightly, and because Alpine has compatibility quirks, I would like to suggest adding this Dockerfile (or something like it) to the Rocket documentation. My understanding is this will likely change when Rocket is available on stable.

# -*- mode: dockerfile -*-

# ------------------------------------------------------------------------------
# Cargo Build Stage
# ------------------------------------------------------------------------------

FROM alpine:latest as builder

# Update the system as needed
RUN apk update

# Install typical system packages we use for building our app.
RUN apk add binutils build-base ca-certificates curl file g++ gcc libressl-dev make patch postgresql rust sqlite

# Install Rust with typical settings and as a typical user.
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

# Install Rust nightly and target for musl 
RUN . ~/.cargo/env && rustup toolchain install nightly 
RUN . ~/.cargo/env && rustup default nightly
RUN . ~/.cargo/env && rustup target add x86_64-unknown-linux-musl

WORKDIR /usr/src/demo_rust_rocket

COPY Cargo.toml Cargo.toml

RUN mkdir src/

RUN echo "fn main() {println!(\"if you see this, the build broke\")}" > src/main.rs

RUN . ~/.cargo/env && RUSTFLAGS="-C target-feature=-crt-static" cargo build --release --target=x86_64-unknown-linux-musl

RUN rm -f target/x86_64-unknown-linux-musl/release/deps/demo_rust_rocket*

COPY . .

# ------------------------------------------------------------------------------
# Final Stage
# ------------------------------------------------------------------------------

FROM alpine:latest

RUN addgroup -g 1000 demo_rust_rocket

RUN adduser -D -s /bin/sh -u 1000 -G demo_rust_rocket demo_rust_rocket

WORKDIR /home/demo_rust_rocket/bin/

COPY --from=builder /usr/src/demo_rust_rocket/target/x86_64-unknown-linux-musl/release/demo_rust_rocket .

RUN chown demo_rust_rocket:demo_rust_rocket demo_rust_rocket

USER demo_rust_rocket

CMD ["./demo_rust_rocket"]
@conways-glider
Copy link
Contributor

Why not start with the alpine version of the Rust docker image?

@joelparkerhenderson
Copy link
Author

joelparkerhenderson commented Jun 14, 2020

Why not start with the alpine version of the Rust docker image?

That's a good idea. To get Rust nightly + Alpine latest, what would you use for "FROM"?

@olback
Copy link
Contributor

olback commented Jun 14, 2020

@joelparkerhenderson Here is a list of all official Rust docker images: https://hub.docker.com/_/rust?tab=tags

@joelparkerhenderson
Copy link
Author

joelparkerhenderson commented Jun 15, 2020

@olback Thank you. At that link, which image is Rust nightly + Alpine latest?

@bkspace
Copy link

bkspace commented Jun 15, 2020

@joelparkerhenderson - you'll want something like:

FROM rustlang/rust:nightly-alpine AS builder

@olback
Copy link
Contributor

olback commented Jun 15, 2020

@joelparkerhenderson I didn't find a alpine nightly but threw is rust:alpine3.11. You would have to install nightly yourself I think. Rust is already there though so it should be a lot faster than doing it from scratch.

@bkspace
Copy link

bkspace commented Jun 15, 2020

https://hub.docker.com/r/rustlang/rust/tags (there's a 3.12 + nightly there)

FROM rustlang/rust:nightly-alpine3.12 AS builder

@joelparkerhenderson
Copy link
Author

FROM rustlang/rust:nightly-alpine

FROM rustlang/rust:nightly-alpine3.12

I didn't find a alpine nightly

Thanks all! Right, I agree that link is the place to look. It doesn't seem to have Alpine latest + Rust nightly. I want the newest Alpine and newest Rust i.e. free of version numbers.

@samuelpilz
Copy link

For building with postgres-connection (feature diesel_postgres_pool), I needed the apk package postgresql-dev

@mickvangelderen
Copy link

@joelparkerhenderson I just run rustup default nightly on a standard rust image. I also copy the toml and lock files with a stand in lib.rs or main.rs to cache dependencies in a layer before adding in the main code. My server app has a local dependency my database lib causing the below file to be larger than necessary when you're building an application without local (path) dependencies. Anyway, here it is:

FROM rust:1.46 as build

RUN rustup default nightly

WORKDIR /usr/src/app

# Caches build dependencies by writing placeholder lib and main files.
COPY Cargo.toml Cargo.lock ./
COPY database/Cargo.toml database/
RUN mkdir -p database/src && echo '' > database/src/lib.rs
COPY server/Cargo.toml server/
RUN mkdir -p server/src && echo 'fn main() {}' > server/src/main.rs

RUN cargo build --package aries_api --release

COPY ./ ./

# Without these lines cargo won't recompile.
RUN touch database/src/lib.rs
RUN touch server/src/main.rs

RUN cargo build --package server --release

FROM debian:buster-slim

RUN apt-get update
RUN apt-get install -y libpq-dev

COPY --from=build /usr/src/app/target/release/server /usr/local/bin/server

CMD ["server"]

Not sure if doing these things is a good idea but it has been working quite well for me.

@frgomes
Copy link

frgomes commented Apr 7, 2021

You guys may eventually find this link below useful. It's not a Dockerfile, it's a shell script which employs buildah, which allows far more flexibility than a Dockerfile. I'm installing Rust from scratch, employing rustup and passing a list of toolchains and targets I'm interested. You can specify alpine on line 77. Obviously it would be necessary to remove the stuff not needed for your purposes.

https://github.com/frgomes/bash-scripts/blob/master/bin/miniglue

@SergioBenitez
Copy link
Member

We've also got #171 open, so closing in favor of that.

@joelparkerhenderson
Copy link
Author

joelparkerhenderson commented May 27, 2021

Would it be OK to reopen this for now? This issue #1322 focuses on local development via a custom Docker file which aims for one local solution, whereas #171 focuses on remote deployment via a standard Docker file and aims for many cloud providers.

My guess is this issue #1322 is likely to be a helpful step toward #171. So it makes sense to me to keep both issues open because this issue's surface area is much smaller, i.e. this issue doesn't need any comments about remote providers, or cloud services, or service company policies, or deployment kits, etc.

Thanks for your consideration.

@SergioBenitez SergioBenitez reopened this May 27, 2021
@SergioBenitez
Copy link
Member

Sure! Is the hope that we would add a blessed sort of configuration of this sort to Rocket's official documentation? Besides avoiding a local Rust installation, what advantage does this setup give you? While I understand why you might want to dockerize development for other projects, I don't quite see the advantages in this case given the self-contained nature of cargo. It seems to me that local development without the introduction of an intermediary is bound to be the least error prone and most efficient path forward, and officially instructing otherwise may lead users down a more complicated, error-prone path.

@joelparkerhenderson
Copy link
Author

Thank you for reopening.

Yes you're correct, my first hope is for some sort of documentation of a minimal docker install of Rocket.

Besides avoiding a local Rust installation

The containerized environment ensures all the developers have the same Rocket setup, versions, paths, etc., and don't have stable, so the environment is guaranteed to be accurate and consistent among all the developers-- and can be created and destroyed at will without affecting the local user directories such as ~/.cargo.

I don't quite see the advantages in this case given the self-contained nature of cargo.

The use case for me is being able to extend a minimal install docker file, to distribute an entire Rocket app and development environment, to help coders who are in resource-controlled organizations where the person can't install Rust locally. I'm aiming for a docker file that includes a bunch of developer-oriented CLI tools (e.g. ripgrep) and servers (e.g. postgresql).

@rwf2 rwf2 locked and limited conversation to collaborators Jul 1, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants