From f6de558070c4ed4dbecf4bbbf4693e396a5577dc Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Wed, 14 Apr 2021 18:40:50 +0100 Subject: [PATCH] Optimise docker (#34) * Smaller dockerfile, better error handling * Add config dir --- .dockerignore | 1 + Cargo.lock | 82 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + Dockerfile | 32 ++++++++++++++--- README.md | 18 +++++----- src/command/server.rs | 3 +- src/main.rs | 2 ++ src/remote/database.rs | 16 ++++++--- src/remote/server.rs | 12 ++++--- src/settings.rs | 2 +- 10 files changed, 144 insertions(+), 25 deletions(-) diff --git a/.dockerignore b/.dockerignore index 9fe342c..1f5346b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ ./target +Dockerfile diff --git a/Cargo.lock b/Cargo.lock index 315ea66..24df36e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aead" version = "0.2.0" @@ -120,6 +135,7 @@ dependencies = [ "eyre", "fern", "fork", + "human-panic", "indicatif", "itertools", "log 0.4.14", @@ -150,6 +166,20 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" +dependencies = [ + "addr2line", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.9.3" @@ -822,6 +852,12 @@ dependencies = [ "polyval", ] +[[package]] +name = "gimli" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" + [[package]] name = "glob" version = "0.3.0" @@ -937,6 +973,21 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +[[package]] +name = "human-panic" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39f357a500abcbd7c5f967c1d45c8838585b36743823b9d43488f24850534e36" +dependencies = [ + "backtrace", + "os_type", + "serde 1.0.125", + "serde_derive", + "termcolor", + "toml 0.5.8", + "uuid", +] + [[package]] name = "hyper" version = "0.10.16" @@ -1261,6 +1312,16 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "mio" version = "0.6.23" @@ -1501,6 +1562,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +[[package]] +name = "object" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + [[package]] name = "once_cell" version = "1.5.2" @@ -1546,6 +1613,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_type" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edc011af0ae98b7f88cf7e4a83b70a54a75d2b8cb013d6efd02e5956207e9eb" +dependencies = [ + "regex", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -2142,6 +2218,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" +[[package]] +name = "rustc-demangle" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" + [[package]] name = "rustc-serialize" version = "0.3.24" diff --git a/Cargo.toml b/Cargo.toml index 9d33787..66955c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ fork = "0.1.18" parse_duration = "2.1.1" rand = "0.8.3" rust-crypto = "^0.2" +human-panic = "1.0.3" [dependencies.rusqlite] version = "0.25" diff --git a/Dockerfile b/Dockerfile index 4ef5f15..774468e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,34 @@ -# no point in tagging the rust version, currently using nightly -FROM rust:slim-buster +FROM rust as builder -RUN apt update && apt -y install libssl-dev libpq-dev pkg-config make RUN rustup default nightly + +RUN cargo new --bin atuin WORKDIR /atuin -COPY . /atuin +COPY ./Cargo.toml ./Cargo.toml +COPY ./Cargo.lock ./Cargo.lock RUN cargo build --release -ENTRYPOINT ["/atuin/target/release/atuin"] +RUN rm src/*.rs + +ADD . ./ + +RUN rm ./target/release/deps/atuin* +RUN cargo build --release + +FROM debian:buster-slim + +RUN apt-get update \ + && apt-get install -y ca-certificates tzdata libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +EXPOSE 8888 + +ENV TZ=Etc/UTC +ENV RUST_LOG=info +ENV ATUIN_CONFIG=/config/config.toml + +COPY --from=builder /atuin/target/release/atuin ./atuin + +ENTRYPOINT ["./atuin"] diff --git a/README.md b/README.md index 7874789..76289fa 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- A'tuin + A'Tuin

Through the fathomless deeps of space swims the star turtle Great A’Tuin, bearing on its back the four giant elephants who carry on their shoulders the mass of the Discworld. @@ -12,11 +12,11 @@

-A'tuin manages and synchronizes your shell history! Instead of storing -everything in a text file (such as ~/.history), A'tuin uses a sqlite database. +A'Tuin manages and synchronizes your shell history! Instead of storing +everything in a text file (such as ~/.history), A'Tuin uses a sqlite database. While being a little more complex, this allows for more functionality. -As well as the expected command, A'tuin stores +As well as the expected command, A'Tuin stores - duration - exit code @@ -33,7 +33,7 @@ As well as the expected command, A'tuin stores ### AUR -A'tuin is available on the [AUR](https://aur.archlinux.org/packages/atuin/) +A'Tuin is available on the [AUR](https://aur.archlinux.org/packages/atuin/) ``` yay -S atuin # or your AUR helper of choice @@ -73,7 +73,7 @@ to your `.zshrc`/`.bashrc`/whatever your shell uses. ### History search -By default A'tuin will rebind ctrl-r and the up arrow to search your history. +By default A'Tuin will rebind ctrl-r and the up arrow to search your history. You can prevent this by putting @@ -119,7 +119,7 @@ atuin h l -s # similarly short ### Stats -A'tuin can calculate statistics for a single day, and accepts "natural language" style date input, as well as absolute dates: +A'Tuin can calculate statistics for a single day, and accepts "natural language" style date input, as well as absolute dates: ``` $ atuin stats day last friday @@ -155,7 +155,7 @@ $ atuin stats all ## Config -A'tuin is configurable via TOML. The file lives at ` ~/.config/atuin/config.toml`, +A'Tuin is configurable via TOML. The file lives at ` ~/.config/atuin/config.toml`, and looks like this: ``` @@ -169,5 +169,5 @@ path = "~/.local/share/atuin/history.db" # the local database for history ## ...what's with the name? -A'tuin is named after "The Great A'tuin", a giant turtle from Terry Pratchett's +A'Tuin is named after "The Great A'Tuin", a giant turtle from Terry Pratchett's Discworld series of books. diff --git a/src/command/server.rs b/src/command/server.rs index ba2a9a2..bf75794 100644 --- a/src/command/server.rs +++ b/src/command/server.rs @@ -29,9 +29,8 @@ impl Cmd { ); let port = port.map_or(settings.server.port, |p| p); - server::launch(settings, host, port); + server::launch(settings, host, port) } } - Ok(()) } } diff --git a/src/main.rs b/src/main.rs index ae45980..94c7366 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use eyre::{eyre, Result}; +use human_panic::setup_panic; use structopt::{clap::AppSettings, StructOpt}; #[macro_use] @@ -73,6 +74,7 @@ impl Atuin { } fn main() -> Result<()> { + setup_panic!(); let settings = Settings::new()?; fern::Dispatch::new() diff --git a/src/remote/database.rs b/src/remote/database.rs index ddcffda..03973ca 100644 --- a/src/remote/database.rs +++ b/src/remote/database.rs @@ -1,5 +1,6 @@ use diesel::pg::PgConnection; use diesel::prelude::*; +use eyre::{eyre, Result}; use crate::settings::Settings; @@ -7,8 +8,15 @@ use crate::settings::Settings; pub struct AtuinDbConn(diesel::PgConnection); // TODO: connection pooling -pub fn establish_connection(settings: &Settings) -> PgConnection { - let database_url = &settings.server.db_uri; - PgConnection::establish(database_url) - .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) +pub fn establish_connection(settings: &Settings) -> Result { + if settings.server.db_uri == "default_uri" { + Err(eyre!( + "Please configure your database! Set db_uri in config.toml" + )) + } else { + let database_url = &settings.server.db_uri; + let conn = PgConnection::establish(database_url)?; + + Ok(conn) + } } diff --git a/src/remote/server.rs b/src/remote/server.rs index de58397..ee481ca 100644 --- a/src/remote/server.rs +++ b/src/remote/server.rs @@ -1,5 +1,3 @@ -use rocket::config::{Config, Environment, LoggingLevel, Value}; - use std::collections::HashMap; use crate::remote::database::establish_connection; @@ -7,6 +5,9 @@ use crate::settings::Settings; use super::database::AtuinDbConn; +use eyre::Result; +use rocket::config::{Config, Environment, LoggingLevel, Value}; + // a bunch of these imports are generated by macros, it's easier to wildcard #[allow(clippy::clippy::wildcard_imports)] use super::views::*; @@ -16,7 +17,7 @@ use super::auth::*; embed_migrations!("migrations"); -pub fn launch(settings: &Settings, host: String, port: u16) { +pub fn launch(settings: &Settings, host: String, port: u16) -> Result<()> { let settings: Settings = settings.clone(); // clone so rocket can manage it let mut database_config = HashMap::new(); @@ -25,7 +26,8 @@ pub fn launch(settings: &Settings, host: String, port: u16) { database_config.insert("url", Value::from(settings.server.db_uri.clone())); databases.insert("atuin", Value::from(database_config)); - let connection = establish_connection(&settings); + let connection = establish_connection(&settings)?; + embedded_migrations::run(&connection).expect("failed to run migrations"); let config = Config::build(Environment::Production) @@ -54,4 +56,6 @@ pub fn launch(settings: &Settings, host: String, port: u16) { .attach(AtuinDbConn::fairing()) .register(catchers![internal_error, bad_request]) .launch(); + + Ok(()) } diff --git a/src/settings.rs b/src/settings.rs index 5d19699..f3bc62e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -133,7 +133,7 @@ impl Settings { s.set_default("server.host", "127.0.0.1")?; s.set_default("server.port", 8888)?; s.set_default("server.open_registration", false)?; - s.set_default("server.db_uri", "DEFAULT POSTGRES URI, PLEASE CHANGE")?; + s.set_default("server.db_uri", "default_uri")?; if config_file.exists() { s.merge(ConfigFile::with_name(config_file.to_str().unwrap()))?;