Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Dockerize Medea #35

Merged
merged 10 commits into from
Jul 18, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
*
# Medea sources and manifest
!Cargo.toml
!Cargo.lock
!src

# Medea uses this crates
!crates
!proto

# We dont need jason while building medea, but since its
# in medea's workspace we must give cargo this files
!jason/Cargo.toml
!jason/src/lib.rs

# Medea dependencies cache
!.cache/cargo/

# !target/&{mode} will be added and removed dynamically
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
RUST_LOG=debug
MEDEA_CONF=config.toml

COMPOSE_PROJECT_NAME=medea
COMPOSE_IMAGE_NAME=instrumentisto/medea
994 changes: 507 additions & 487 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ macro-attr = "0.2"
medea-client-api-proto = { path = "proto/client-api", features = ["medea"] }
medea-macro = { path = "crates/medea-macro" }
newtype_derive = "0.1"
rand = "0.6"
rand = "0.7"
redis = "0.10"
rust-crypto = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
slog = "2.4"
slog = "2.5"
slog-async = "2.3"
slog-envlogger = "2.1"
slog-json = "2.3"
Expand Down
49 changes: 49 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#
# Stage 'dist' creates project distribution.
#

# https://hub.docker.com/_/rust
ARG rust_ver=latest
FROM rust:${rust_ver} AS dist
ARG rustc_mode=release
ARG rustc_opts=--release
ARG cargo_home=/usr/local/cargo

# Create the user and group files that will be used in the running container to
# run the process as an unprivileged user.
RUN mkdir -p /out/etc/ \
&& echo 'nobody:x:65534:65534:nobody:/:' > /out/etc/passwd \
&& echo 'nobody:x:65534:' > /out/etc/group

COPY / /app/

# Build project distribution.
RUN cd /app \
# Compile project.
&& CARGO_HOME="${cargo_home}" \
# TODO: use --out-dir once stabilized
# TODO: https://github.com/rust-lang/cargo/issues/6790
cargo build --offline --bin=medea ${rustc_opts} \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, we cannot use --offline. The image should be able to build without Makefile at all. That's exactly what would happen on Docker Hub.

Makefile here only gives us "tricks" to reduce image build time during dev/CI.

# Prepare the binary and all dependent dynamic libraries.
&& cp /app/target/${rustc_mode}/medea /out/medea \
&& ldd /out/medea \
| awk 'BEGIN{ORS=" "}$1~/^\//{print $1}$3~/^\//{print $3}' \
| sed 's/,$/\n/' \
| tr ' ' "\n" \
| xargs -I '{}' cp -fL --parents '{}' /out/




#
# Stage 'runtime' creates final Docker image to use in runtime.
#

# https://hub.docker.com/_/scratch
FROM scratch AS runtime

COPY --from=dist /out/ /

USER nobody:nobody

ENTRYPOINT ["/medea"]
50 changes: 48 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,23 @@ eq = $(if $(or $(1),$(2)),$(and $(findstring $(1),$(2)),\



######################
# Project parameters #
######################

IMAGE_NAME := $(strip $(shell grep 'COMPOSE_IMAGE_NAME=' .env | cut -d '=' -f2))

RUST_VER := 1.36.0




###########
# Aliases #
###########

build: docker.build

# Resolve all project dependencies.
#
# Usage:
Expand Down Expand Up @@ -122,6 +135,39 @@ endif



###################
# Docker commands #
###################

# Build medea project Docker image.
#
# Usage:
# make docker.build [TAG=(dev|<tag>)] [debug=(yes|no)] [no-cache=(no|yes)]

docker-build-image-name = $(IMAGE_NAME)$(if $(call eq,$(IMAGE),),,/$(IMAGE))

docker.build:
ifneq ($(no-cache),yes)
docker run -u $(shell id -u):$(shell id -g) --rm --network=host -v "$(PWD)":/app -w /app \
-e CARGO_HOME=.cache/cargo \
rust:$(RUST_VER) \
cargo build --bin=medea \
$(if $(call eq,$(debug),no),--release,)
endif
@echo "!target/$(if $(call eq,$(debug),no),release,debug)/" >> .dockerignore
- docker build --network=host --force-rm \
$(if $(call eq,$(no-cache),yes),\
--no-cache --pull,) \
$(if $(call eq,$(IMAGE),),\
--build-arg rust_ver=$(RUST_VER) \
--build-arg rustc_mode=$(if \
$(call eq,$(debug),no),release,debug) \
--build-arg rustc_opts=$(if \
$(call eq,$(debug),no),--release,) \
--build-arg cargo_home=.cache/cargo,) \
-t $(docker-build-image-name):$(if $(call eq,$(TAG),),dev,$(TAG)) .
@sed -i '/!target\/$(if $(call eq,$(debug),no),release,debug)/d' .dockerignore


####################
# Testing commands #
Expand Down Expand Up @@ -191,8 +237,8 @@ up.medea:
# .PHONY section #
##################

.PHONY: cargo cargo.fmt cargo.lint \
docs docs.rust \
.PHONY: build cargo cargo.fmt cargo.lint \
docker.build docs docs.rust \
test test.unit \
up up.coturn up.jason up.medea \
yarn
Expand Down
9 changes: 9 additions & 0 deletions config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,12 @@
#
# Default:
# connection_timeout = "5s"

[log.app]
# Maximum allowed level of application log entries.
#
# Possible values:
# ["OFF", "CRITICAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]
#
# Default:
# level = "INFO"
1 change: 1 addition & 0 deletions src/api/client/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ mod test {
},
turn: Turn::default(),
server: Server::default(),
log: Default::default(),
};

let mut server = ws_server(conf.clone());
Expand Down
31 changes: 31 additions & 0 deletions src/conf/logs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! Logs settings.
use std::str::FromStr as _;

use serde::{Deserialize, Serialize};
use smart_default::*;

/// Logs settings.
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(default)]
pub struct Logs {
/// Application log settings.
pub app: AppLog,
}

/// Application log settings.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, SmartDefault)]
#[serde(default)]
pub struct AppLog {
// Maximum allowed level of application log entries.
//
// Defaults to `INFO`.
#[default(String::from("INFO"))]
level: String,
}

impl AppLog {
/// Returns configured application logging level. None if disabled.
pub fn level(&self) -> Option<slog::Level> {
slog::Level::from_str(&self.level).ok()
}
}
26 changes: 24 additions & 2 deletions src/conf/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Provides application configuration options.

pub mod logs;
pub mod rpc;
pub mod server;
pub mod turn;
Expand All @@ -11,6 +12,7 @@ use failure::Error;
use serde::{Deserialize, Serialize};

pub use self::{
logs::Logs,
rpc::Rpc,
server::Server,
turn::{Redis, Turn},
Expand All @@ -33,6 +35,8 @@ pub struct Conf {
pub server: Server,
/// TURN server settings.
pub turn: Turn,
/// Logs settings.
pub log: Logs,
}

impl Conf {
Expand Down Expand Up @@ -196,7 +200,7 @@ mod tests {

#[test]
#[serial]
fn redis_conf_test() {
fn redis_conf() {
let default_conf = Conf::default();

env::set_var("MEDEA_TURN.DB.REDIS.IP", "5.5.5.5");
Expand Down Expand Up @@ -225,7 +229,7 @@ mod tests {

#[test]
#[serial]
fn turn_conf_test() {
fn turn_conf() {
let default_conf = Conf::default();

env::set_var("MEDEA_TURN.IP", "5.5.5.5");
Expand All @@ -240,4 +244,22 @@ mod tests {
assert_eq!(env_conf.turn.port, 1234);
assert_eq!(env_conf.turn.addr(), "5.5.5.5:1234".parse().unwrap());
}

#[test]
#[serial]
fn log_level_conf() {
let default_conf = Conf::default();

env::set_var("MEDEA_LOG.APP.LEVEL", "WARN");

let env_conf = Conf::parse().unwrap();

assert_ne!(default_conf.log.app.level(), env_conf.log.app.level());

assert_eq!(env_conf.log.app.level(), Some(slog::Level::Warning));

env::set_var("MEDEA_LOG.APP.LEVEL", "OFF");

assert_eq!(Conf::parse().unwrap().log.app.level(), None);
}
}
24 changes: 12 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ use crate::{

fn main() -> io::Result<()> {
dotenv().ok();

let config = Conf::parse().unwrap();

if let Some(lvl) = config.log.app.level() {
std::env::set_var("RUST_LOG", lvl.as_str());
}

let logger = log::new_dual_logger(std::io::stdout(), std::io::stderr());
let _scope_guard = slog_scope::set_global_logger(logger);
slog_stdlog::init().unwrap();

actix::run(move || {
futures::future::lazy(Conf::parse)
.map_err(|err| error!("Error parsing config {:?}", err))
.and_then(|config| {
info!("{:?}", config);
info!("{:?}", config);

new_turn_auth_service(&config.turn)
.map_err(|err| {
error!("Error creating TurnAuthService {:?}", err)
})
.join(Ok(config))
})
.and_then(|(turn_auth_service, config)| {
actix::run(|| {
new_turn_auth_service(&config.turn)
.map_err(|err| error!("Error creating TurnAuthService {:?}", err))
.and_then(|turn_auth_service| {
let members = hashmap! {
1 => Member::new(1, "caller_credentials".to_owned()),
2 => Member::new(2, "responder_credentials".to_owned()),
Expand Down