This is an automated email from the ASF dual-hosted git repository.
agrove pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/master by this push:
new a461e9c Move ballista standalone mode to client (#589)
a461e9c is described below
commit a461e9c1f53a2a89d7bf7fb2e98334c224da13aa
Author: Ximo Guanter <[email protected]>
AuthorDate: Tue Jun 22 14:02:33 2021 +0200
Move ballista standalone mode to client (#589)
---
.github/workflows/rust.yml | 4 +-
ballista/rust/client/Cargo.toml | 6 ++
ballista/rust/client/src/columnar_batch.rs | 4 --
ballista/rust/client/src/context.rs | 70 ++++++++++++++++++----
ballista/rust/executor/Cargo.toml | 3 +-
ballista/rust/executor/executor_config_spec.toml | 9 ---
ballista/rust/executor/src/execution_loop.rs | 3 +-
ballista/rust/executor/src/lib.rs | 4 ++
ballista/rust/executor/src/main.rs | 73 ++---------------------
ballista/rust/executor/src/standalone.rs | 72 ++++++++++++++++++++++
ballista/rust/scheduler/Cargo.toml | 3 +-
ballista/rust/scheduler/src/lib.rs | 4 ++
ballista/rust/scheduler/src/standalone.rs | 54 +++++++++++++++++
benchmarks/src/bin/tpch.rs | 7 +--
dev/docker/ballista-base.dockerfile | 2 +-
dev/docker/ballista.dockerfile | 2 +-
docs/user-guide/src/distributed/docker-compose.md | 22 +++++--
17 files changed, 227 insertions(+), 115 deletions(-)
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 7a2890c..4a994bf 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -69,7 +69,7 @@ jobs:
run: |
cd ballista/rust
# snmalloc requires cmake so build without default features
- cargo build --no-default-features
+ cargo build --no-default-features --features sled
env:
CARGO_HOME: "/github/home/.cargo"
CARGO_TARGET_DIR: "/github/home/target"
@@ -131,7 +131,7 @@ jobs:
export PARQUET_TEST_DATA=$(pwd)/parquet-testing/data
cd ballista/rust
# snmalloc requires cmake so build without default features
- cargo test --no-default-features
+ cargo test --no-default-features --features sled
env:
CARGO_HOME: "/github/home/.cargo"
CARGO_TARGET_DIR: "/github/home/target"
diff --git a/ballista/rust/client/Cargo.toml b/ballista/rust/client/Cargo.toml
index dd1a57c..5c7eb38 100644
--- a/ballista/rust/client/Cargo.toml
+++ b/ballista/rust/client/Cargo.toml
@@ -27,8 +27,14 @@ edition = "2018"
[dependencies]
ballista-core = { path = "../core" }
+ballista-executor = { path = "../executor", optional = true }
+ballista-scheduler = { path = "../scheduler", optional = true }
futures = "0.3"
log = "0.4"
tokio = "1.0"
datafusion = { path = "../../../datafusion" }
+
+[features]
+default = []
+standalone = ["ballista-executor", "ballista-scheduler"]
\ No newline at end of file
diff --git a/ballista/rust/client/src/columnar_batch.rs
b/ballista/rust/client/src/columnar_batch.rs
index a40b68f..3431f56 100644
--- a/ballista/rust/client/src/columnar_batch.rs
+++ b/ballista/rust/client/src/columnar_batch.rs
@@ -29,9 +29,7 @@ use datafusion::scalar::ScalarValue;
pub type MaybeColumnarBatch = Result<Option<ColumnarBatch>>;
/// Batch of columnar data.
-#[allow(dead_code)]
#[derive(Debug, Clone)]
-
pub struct ColumnarBatch {
schema: Arc<Schema>,
columns: HashMap<String, ColumnarValue>,
@@ -112,9 +110,7 @@ impl ColumnarBatch {
}
/// A columnar value can either be a scalar value or an Arrow array.
-#[allow(dead_code)]
#[derive(Debug, Clone)]
-
pub enum ColumnarValue {
Scalar(ScalarValue, usize),
Columnar(ArrayRef),
diff --git a/ballista/rust/client/src/context.rs
b/ballista/rust/client/src/context.rs
index 695045d..aca712e 100644
--- a/ballista/rust/client/src/context.rs
+++ b/ballista/rust/client/src/context.rs
@@ -44,7 +44,6 @@ use futures::future;
use futures::StreamExt;
use log::{error, info};
-#[allow(dead_code)]
struct BallistaContextState {
/// Scheduler host
scheduler_host: String,
@@ -52,26 +51,48 @@ struct BallistaContextState {
scheduler_port: u16,
/// Tables that have been registered with this context
tables: HashMap<String, LogicalPlan>,
- /// General purpose settings
- settings: HashMap<String, String>,
}
impl BallistaContextState {
- pub fn new(
- scheduler_host: String,
- scheduler_port: u16,
- settings: HashMap<String, String>,
- ) -> Self {
+ pub fn new(scheduler_host: String, scheduler_port: u16) -> Self {
Self {
scheduler_host,
scheduler_port,
tables: HashMap::new(),
- settings,
}
}
-}
-#[allow(dead_code)]
+ #[cfg(feature = "standalone")]
+ pub async fn new_standalone(
+ concurrent_tasks: usize,
+ ) -> ballista_core::error::Result<Self> {
+ info!("Running in local mode. Scheduler will be run in-proc");
+
+ let addr = ballista_scheduler::new_standalone_scheduler().await?;
+
+ let scheduler = loop {
+ match SchedulerGrpcClient::connect(format!(
+ "http://localhost:{}",
+ addr.port()
+ ))
+ .await
+ {
+ Err(_) => {
+ tokio::time::sleep(Duration::from_millis(100)).await;
+ info!("Attempting to connect to in-proc scheduler...");
+ }
+ Ok(scheduler) => break scheduler,
+ }
+ };
+
+ ballista_executor::new_standalone_executor(scheduler,
concurrent_tasks).await?;
+ Ok(Self {
+ scheduler_host: "localhost".to_string(),
+ scheduler_port: addr.port(),
+ tables: HashMap::new(),
+ })
+ }
+}
pub struct BallistaContext {
state: Arc<Mutex<BallistaContextState>>,
@@ -79,14 +100,25 @@ pub struct BallistaContext {
impl BallistaContext {
/// Create a context for executing queries against a remote Ballista
scheduler instance
- pub fn remote(host: &str, port: u16, settings: HashMap<String, String>) ->
Self {
- let state = BallistaContextState::new(host.to_owned(), port, settings);
+ pub fn remote(host: &str, port: u16) -> Self {
+ let state = BallistaContextState::new(host.to_owned(), port);
Self {
state: Arc::new(Mutex::new(state)),
}
}
+ #[cfg(feature = "standalone")]
+ pub async fn standalone(
+ concurrent_tasks: usize,
+ ) -> ballista_core::error::Result<Self> {
+ let state =
BallistaContextState::new_standalone(concurrent_tasks).await?;
+
+ Ok(Self {
+ state: Arc::new(Mutex::new(state)),
+ })
+ }
+
/// Create a DataFrame representing a Parquet table scan
pub fn read_parquet(&self, path: &str) -> Result<Arc<dyn DataFrame>> {
@@ -268,3 +300,15 @@ impl BallistaContext {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ #[tokio::test]
+ #[cfg(feature = "standalone")]
+ async fn test_standalone_mode() {
+ use super::*;
+ let context = BallistaContext::standalone(1).await.unwrap();
+ let df = context.sql("SELECT 1;").unwrap();
+ context.collect(&df.to_logical_plan()).await.unwrap();
+ }
+}
diff --git a/ballista/rust/executor/Cargo.toml
b/ballista/rust/executor/Cargo.toml
index 7574fca..68e4920 100644
--- a/ballista/rust/executor/Cargo.toml
+++ b/ballista/rust/executor/Cargo.toml
@@ -32,7 +32,6 @@ snmalloc = ["snmalloc-rs"]
anyhow = "1"
async-trait = "0.1.36"
ballista-core = { path = "../core" }
-ballista-scheduler = { path = "../scheduler" }
configure_me = "0.4.0"
env_logger = "0.8"
futures = "0.3"
@@ -40,7 +39,7 @@ log = "0.4"
snmalloc-rs = {version = "0.2", features= ["cache-friendly"], optional = true}
tempfile = "3"
tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread"] }
-tokio-stream = "0.1"
+tokio-stream = { version = "0.1", features = ["net"] }
tonic = "0.4"
uuid = { version = "0.8", features = ["v4"] }
diff --git a/ballista/rust/executor/executor_config_spec.toml
b/ballista/rust/executor/executor_config_spec.toml
index 3cb168e..6f170c8 100644
--- a/ballista/rust/executor/executor_config_spec.toml
+++ b/ballista/rust/executor/executor_config_spec.toml
@@ -36,10 +36,6 @@ type = "u16"
default = "50050"
doc = "scheduler port"
-[[switch]]
-name = "local"
-doc = "Running in local mode will launch a standalone scheduler inside the
executor process. This will create a single-executor cluster, and is useful for
development scenarios."
-
[[param]]
name = "bind_host"
type = "String"
@@ -69,8 +65,3 @@ name = "concurrent_tasks"
type = "usize"
default = "4"
doc = "Max concurrent tasks."
-
-[[param]]
-name = "scheduler_data_path"
-type = "String"
-doc = "Path for standalone data"
diff --git a/ballista/rust/executor/src/execution_loop.rs
b/ballista/rust/executor/src/execution_loop.rs
index afc6f00..6eb4713 100644
--- a/ballista/rust/executor/src/execution_loop.rs
+++ b/ballista/rust/executor/src/execution_loop.rs
@@ -29,9 +29,10 @@ use ballista_core::serde::protobuf::{
self, scheduler_grpc_client::SchedulerGrpcClient, task_status, FailedTask,
PartitionId, PollWorkParams, PollWorkResult, TaskDefinition, TaskStatus,
};
-use ballista_executor::executor::Executor;
use protobuf::CompletedTask;
+use crate::executor::Executor;
+
pub async fn poll_loop(
mut scheduler: SchedulerGrpcClient<Channel>,
executor: Arc<Executor>,
diff --git a/ballista/rust/executor/src/lib.rs
b/ballista/rust/executor/src/lib.rs
index 188b944..f3ab7dc 100644
--- a/ballista/rust/executor/src/lib.rs
+++ b/ballista/rust/executor/src/lib.rs
@@ -18,5 +18,9 @@
//! Core executor logic for executing queries and storing results in memory.
pub mod collect;
+pub mod execution_loop;
pub mod executor;
pub mod flight_service;
+
+mod standalone;
+pub use standalone::new_standalone_executor;
diff --git a/ballista/rust/executor/src/main.rs
b/ballista/rust/executor/src/main.rs
index 4c63ba8..b411a77 100644
--- a/ballista/rust/executor/src/main.rs
+++ b/ballista/rust/executor/src/main.rs
@@ -17,14 +17,11 @@
//! Ballista Rust executor binary.
-use std::{
- net::{IpAddr, Ipv4Addr},
- sync::Arc,
-};
+use std::sync::Arc;
use anyhow::{Context, Result};
use arrow_flight::flight_service_server::FlightServiceServer;
-use futures::future::MaybeDone;
+use ballista_executor::execution_loop;
use log::info;
use tempfile::TempDir;
use tonic::transport::Server;
@@ -34,17 +31,11 @@ use ballista_core::serde::protobuf::{
executor_registration, scheduler_grpc_client::SchedulerGrpcClient,
ExecutorRegistration,
};
-use ballista_core::{
- print_version, serde::protobuf::scheduler_grpc_server::SchedulerGrpcServer,
- BALLISTA_VERSION,
-};
+use ballista_core::{print_version, BALLISTA_VERSION};
use ballista_executor::executor::Executor;
use ballista_executor::flight_service::BallistaFlightService;
-use ballista_scheduler::{state::StandaloneClient, SchedulerServer};
use config::prelude::*;
-mod execution_loop;
-
#[macro_use]
extern crate configure_me;
@@ -82,11 +73,7 @@ async fn main() -> Result<()> {
.parse()
.with_context(|| format!("Could not parse address: {}", addr))?;
- let scheduler_host = if opt.local {
- "localhost".to_string()
- } else {
- opt.scheduler_host
- };
+ let scheduler_host = opt.scheduler_host;
let scheduler_port = opt.scheduler_port;
let scheduler_url = format!("http://{}:{}", scheduler_host,
scheduler_port);
@@ -109,58 +96,6 @@ async fn main() -> Result<()> {
port: port as u32,
};
- if opt.local {
- info!("Running in local mode. Scheduler will be run in-proc");
-
- let client = match opt.scheduler_data_path {
- Some(v) => StandaloneClient::try_new(v)
- .context("Could not create standalone config backend")?,
- None => StandaloneClient::try_new_temporary()
- .context("Could not create standalone config backend")?,
- };
-
- let server = SchedulerGrpcServer::new(SchedulerServer::new(
- Arc::new(client),
- "ballista".to_string(),
- IpAddr::V4(Ipv4Addr::LOCALHOST),
- ));
- let addr = format!("localhost:{}", scheduler_port);
- let addr = addr
- .parse()
- .with_context(|| format!("Could not parse {}", addr))?;
- info!(
- "Ballista v{} Rust Scheduler listening on {:?}",
- BALLISTA_VERSION, addr
- );
- let scheduler_future =
- tokio::spawn(Server::builder().add_service(server).serve(addr));
- let mut scheduler_result =
futures::future::maybe_done(scheduler_future);
-
- // Ensure scheduler is ready to receive connections
- while SchedulerGrpcClient::connect(scheduler_url.clone())
- .await
- .is_err()
- {
- let scheduler_future = match scheduler_result {
- MaybeDone::Future(f) => f,
- MaybeDone::Done(Err(e)) => return Err(e).context("Tokio
error"),
- MaybeDone::Done(Ok(Err(e))) => {
- return Err(e).context("Scheduler failed to initialize
correctly")
- }
- MaybeDone::Done(Ok(Ok(()))) => {
- return Err(anyhow::format_err!(
- "Scheduler unexpectedly finished successfully"
- ))
- }
- MaybeDone::Gone => {
- panic!("Received Gone from recently created MaybeDone")
- }
- };
- tokio::time::sleep(std::time::Duration::from_millis(100)).await;
- scheduler_result = futures::future::maybe_done(scheduler_future);
- }
- }
-
let scheduler = SchedulerGrpcClient::connect(scheduler_url)
.await
.context("Could not connect to scheduler")?;
diff --git a/ballista/rust/executor/src/standalone.rs
b/ballista/rust/executor/src/standalone.rs
new file mode 100644
index 0000000..39a899c
--- /dev/null
+++ b/ballista/rust/executor/src/standalone.rs
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::sync::Arc;
+
+use arrow_flight::flight_service_server::FlightServiceServer;
+use ballista_core::{
+ error::Result,
+ serde::protobuf::{scheduler_grpc_client::SchedulerGrpcClient,
ExecutorRegistration},
+ BALLISTA_VERSION,
+};
+use log::info;
+use tempfile::TempDir;
+use tokio::net::TcpListener;
+use tonic::transport::{Channel, Server};
+use uuid::Uuid;
+
+use crate::{execution_loop, executor::Executor,
flight_service::BallistaFlightService};
+
+pub async fn new_standalone_executor(
+ scheduler: SchedulerGrpcClient<Channel>,
+ concurrent_tasks: usize,
+) -> Result<()> {
+ let work_dir = TempDir::new()?
+ .into_path()
+ .into_os_string()
+ .into_string()
+ .unwrap();
+ let executor = Arc::new(Executor::new(&work_dir));
+
+ let service = BallistaFlightService::new(executor.clone());
+
+ let server = FlightServiceServer::new(service);
+ // Let the OS assign a random, free port
+ let listener = TcpListener::bind("localhost:0").await?;
+ let addr = listener.local_addr()?;
+ info!(
+ "Ballista v{} Rust Executor listening on {:?}",
+ BALLISTA_VERSION, addr
+ );
+ tokio::spawn(
+ Server::builder().add_service(server).serve_with_incoming(
+ tokio_stream::wrappers::TcpListenerStream::new(listener),
+ ),
+ );
+ let executor_meta = ExecutorRegistration {
+ id: Uuid::new_v4().to_string(), // assign this executor a unique ID
+ optional_host: None,
+ port: addr.port() as u32,
+ };
+ tokio::spawn(execution_loop::poll_loop(
+ scheduler,
+ executor,
+ executor_meta,
+ concurrent_tasks,
+ ));
+ Ok(())
+}
diff --git a/ballista/rust/scheduler/Cargo.toml
b/ballista/rust/scheduler/Cargo.toml
index c009cc6..215c58a 100644
--- a/ballista/rust/scheduler/Cargo.toml
+++ b/ballista/rust/scheduler/Cargo.toml
@@ -28,7 +28,7 @@ edition = "2018"
[features]
default = ["etcd", "sled"]
etcd = ["etcd-client"]
-sled = ["sled_package"]
+sled = ["sled_package", "tokio-stream"]
[dependencies]
anyhow = "1"
@@ -48,6 +48,7 @@ rand = "0.8"
serde = {version = "1", features = ["derive"]}
sled_package = { package = "sled", version = "0.34", optional = true }
tokio = { version = "1.0", features = ["full"] }
+tokio-stream = { version = "0.1", features = ["net"], optional = true }
tonic = "0.4"
tower = { version = "0.4" }
warp = "0.3"
diff --git a/ballista/rust/scheduler/src/lib.rs
b/ballista/rust/scheduler/src/lib.rs
index 99c7be6..54cba48 100644
--- a/ballista/rust/scheduler/src/lib.rs
+++ b/ballista/rust/scheduler/src/lib.rs
@@ -19,7 +19,11 @@
pub mod api;
pub mod planner;
+#[cfg(feature = "sled")]
+mod standalone;
pub mod state;
+#[cfg(feature = "sled")]
+pub use standalone::new_standalone_scheduler;
#[cfg(test)]
pub mod test_utils;
diff --git a/ballista/rust/scheduler/src/standalone.rs
b/ballista/rust/scheduler/src/standalone.rs
new file mode 100644
index 0000000..6ab5bd6
--- /dev/null
+++ b/ballista/rust/scheduler/src/standalone.rs
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use ballista_core::{
+ error::Result, serde::protobuf::scheduler_grpc_server::SchedulerGrpcServer,
+ BALLISTA_VERSION,
+};
+use log::info;
+use std::{
+ net::{IpAddr, Ipv4Addr, SocketAddr},
+ sync::Arc,
+};
+use tokio::net::TcpListener;
+use tonic::transport::Server;
+
+use crate::{state::StandaloneClient, SchedulerServer};
+
+pub async fn new_standalone_scheduler() -> Result<SocketAddr> {
+ let client = StandaloneClient::try_new_temporary()?;
+
+ let server = SchedulerGrpcServer::new(SchedulerServer::new(
+ Arc::new(client),
+ "ballista".to_string(),
+ IpAddr::V4(Ipv4Addr::LOCALHOST),
+ ));
+ // Let the OS assign a random, free port
+ let listener = TcpListener::bind("localhost:0").await?;
+ let addr = listener.local_addr()?;
+ info!(
+ "Ballista v{} Rust Scheduler listening on {:?}",
+ BALLISTA_VERSION, addr
+ );
+ tokio::spawn(
+ Server::builder().add_service(server).serve_with_incoming(
+ tokio_stream::wrappers::TcpListenerStream::new(listener),
+ ),
+ );
+
+ Ok(addr)
+}
diff --git a/benchmarks/src/bin/tpch.rs b/benchmarks/src/bin/tpch.rs
index 34b8d3a..08c4763 100644
--- a/benchmarks/src/bin/tpch.rs
+++ b/benchmarks/src/bin/tpch.rs
@@ -18,7 +18,6 @@
//! Benchmark derived from TPC-H. This is not an official TPC-H benchmark.
use std::{
- collections::HashMap,
fs,
iter::Iterator,
path::{Path, PathBuf},
@@ -252,11 +251,7 @@ async fn benchmark_datafusion(opt: DataFusionBenchmarkOpt)
-> Result<Vec<RecordB
async fn benchmark_ballista(opt: BallistaBenchmarkOpt) -> Result<()> {
println!("Running benchmarks with the following options: {:?}", opt);
- let mut settings = HashMap::new();
- settings.insert("batch.size".to_owned(), format!("{}", opt.batch_size));
-
- let ctx =
- BallistaContext::remote(opt.host.unwrap().as_str(), opt.port.unwrap(),
settings);
+ let ctx = BallistaContext::remote(opt.host.unwrap().as_str(),
opt.port.unwrap());
// register tables with Ballista context
let path = opt.path.to_str().unwrap();
diff --git a/dev/docker/ballista-base.dockerfile
b/dev/docker/ballista-base.dockerfile
index 31620b3..e977f5e 100644
--- a/dev/docker/ballista-base.dockerfile
+++ b/dev/docker/ballista-base.dockerfile
@@ -23,7 +23,7 @@
# Base image extends debian:buster-slim
-FROM rust:1.51.0-buster AS builder
+FROM rust:1.52.1-buster AS builder
RUN apt update && apt -y install musl musl-dev musl-tools libssl-dev openssl
diff --git a/dev/docker/ballista.dockerfile b/dev/docker/ballista.dockerfile
index 59f21b7..730e867 100644
--- a/dev/docker/ballista.dockerfile
+++ b/dev/docker/ballista.dockerfile
@@ -91,4 +91,4 @@ COPY benchmarks/queries/ /queries/
ENV RUST_LOG=info
ENV RUST_BACKTRACE=full
-CMD ["/executor", "--local"]
+CMD ["/executor"]
diff --git a/docs/user-guide/src/distributed/docker-compose.md
b/docs/user-guide/src/distributed/docker-compose.md
index 5ea86b5..14989e5 100644
--- a/docs/user-guide/src/distributed/docker-compose.md
+++ b/docs/user-guide/src/distributed/docker-compose.md
@@ -24,23 +24,33 @@ demonstrates how to start a cluster using a single process
that acts as both a s
volume mounted into the container so that Ballista can access the host file
system.
```yaml
-version: "2.0"
+version: '2.2'
services:
etcd:
image: quay.io/coreos/etcd:v3.4.9
command: "etcd -advertise-client-urls http://etcd:2379 -listen-client-urls
http://0.0.0.0:2379"
+ ballista-scheduler:
+ image: ballista:0.5.0-SNAPSHOT
+ command: "/scheduler --config-backend etcd --etcd-urls etcd:2379
--bind-host 0.0.0.0 --bind-port 50050"
ports:
- - "2379:2379"
- ballista-executor:
- image: ballistacompute/ballista-rust:0.4.2-SNAPSHOT
- command: "/executor --bind-host 0.0.0.0 --bind-port 50051 --local"
+ - "50050:50050"
environment:
- RUST_LOG=info
+ volumes:
+ - ./data:/data
+ depends_on:
+ - etcd
+ ballista-executor:
+ image: ballista:0.5.0-SNAPSHOT
+ command: "/executor --bind-host 0.0.0.0 --bind-port 50051 --scheduler-host
ballista-scheduler"
ports:
- - "50050:50050"
- "50051:50051"
+ environment:
+ - RUST_LOG=info
volumes:
- ./data:/data
+ depends_on:
+ - ballista-scheduler
```
With the above content saved to a `docker-compose.yaml` file, the following
command can be used to start the single