Skip to content

Add Docker support #9

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
170 changes: 170 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Stage 1: base image
FROM nvidia/cuda:12.8.0-devel-ubuntu24.04 AS base
ENV DEBIAN_FRONTEND=noninteractive

# set labels
LABEL version="1.0"
LABEL description="DEM-Engine Development and Production Environment"
ARG CUDA_VERSION=12.8.0
ARG UBUNTU_VERSION=24.04
ARG CMAKE_BUILD_TYPE=Release
ARG BUILD_JOBS=0

# basic dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
ninja-build \
git \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# CUDA environment variables
ENV CUDA_HOME=/usr/local/cuda-12.8
ENV LD_LIBRARY_PATH=${CUDA_HOME}/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
ENV CPATH=/usr/local/cuda-12.8/targets/x86_64-linux/include
ENV PATH=/usr/local/cuda-12.8/bin:/usr/local/cuda-12.8/lib64/cmake:${CUDA_HOME}/bin:${PATH}

# Stage 2: dependencies
FROM base AS deps

# necessary libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
libeigen3-dev \
libboost-dev \
libboost-filesystem-dev \
libboost-system-dev \
libboost-thread-dev \
&& rm -rf /var/lib/apt/lists/*

# Stage 3: CUDA headers preparation
FROM base AS cuda-headers

# copy CUDA headers from the base image
RUN mkdir -p /cuda-headers && \
cd /usr/local/cuda-12.8/include && \
cp -r \
cuda.h \
cuda_runtime*.h \
curand*.h \
device_*.h \
driver_types.h \
vector_types.h \
library_types.h \
surface_types.h \
texture_types.h \
channel_descriptor.h \
builtin_types.h \
cuda_fp16.h \
cuda_fp16.hpp \
sm_*.h \
cuda_device_runtime_api.h \
cuda_texture_types.h \
cuda_surface_types.h \
crt \
/cuda-headers/

# Stage 4: build environment
FROM deps AS builder
WORKDIR /workspace/DEM-Engine

# copy CMake configuration files
COPY CMakeLists.txt /workspace/DEM-Engine/
COPY cmake /workspace/DEM-Engine/cmake

# copy source code
COPY src /workspace/DEM-Engine/src
COPY data /workspace/DEM-Engine/data
COPY thirdparty /workspace/DEM-Engine/thirdparty

# build the project
RUN mkdir build && cd build && \
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-Release} \
.. && \
ninja -j${BUILD_JOBS:-$(nproc)}

# Stage 5: runtime image
FROM nvidia/cuda:12.8.0-runtime-ubuntu24.04 AS runtime-base
ENV DEBIAN_FRONTEND=noninteractive

# necessary runtime libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
libgomp1 \
libboost-filesystem1.83.0 \
libboost-system1.83.0 \
libboost-thread1.83.0 \
&& rm -rf /var/lib/apt/lists/*

# CUDA environment variables for runtime
ENV CUDA_HOME=/usr/local/cuda-12.8
ENV LD_LIBRARY_PATH=${CUDA_HOME}/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

# Stage 6: production image
FROM runtime-base AS production

# copy CUDA headers from the cuda-headers stage
COPY --from=cuda-headers /cuda-headers /usr/local/cuda-12.8/include

# copy jitify library
COPY --from=builder /workspace/DEM-Engine/thirdparty /workspace/DEM-Engine/thirdparty

# create directory structure
RUN mkdir -p /workspace/DEM-Engine/build/output \
/workspace/DEM-Engine/output

COPY --from=base /usr/local/cuda-12.8/include /usr/local/cuda-12.8/include

# copy files from building stage
COPY --from=builder /workspace/DEM-Engine/build/bin /workspace/DEM-Engine/build/bin
COPY --from=builder /workspace/DEM-Engine/build/DEM /workspace/DEM-Engine/build/DEM
COPY --from=builder /workspace/DEM-Engine/build/kernel /workspace/DEM-Engine/build/kernel

# set working directory
WORKDIR /workspace/DEM-Engine

# create a wrapper script to ensure correct working directory
RUN echo '#!/bin/bash\ncd /workspace/DEM-Engine\nexec "$@"' > /usr/local/bin/dem-wrapper.sh && \
chmod +x /usr/local/bin/dem-wrapper.sh

# set environment variables
ENV CUDA_PATH=/usr/local/cuda-12.8
ENV CUDA_INC_PATH=/usr/local/cuda-12.8/include
ENV JITIFY_PATH=/workspace/DEM-Engine/thirdparty/jitify
ENV PATH=/workspace/DEM-Engine/build/bin:${PATH}
ENV OMP_NUM_THREADS=8

ENTRYPOINT ["/usr/local/bin/dem-wrapper.sh"]
CMD ["/bin/bash"]

# Stage 7: development image
FROM deps AS development

# debug and development tools
RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
valgrind \
vim \
htop \
curl \
wget \
python3-minimal \
python3-pip \
python3-numpy \
python3-matplotlib \
python3-pandas \
python3-h5py \
&& rm -rf /var/lib/apt/lists/*

# copy source code
COPY . /workspace/DEM-Engine
WORKDIR /workspace/DEM-Engine

# create build directory
RUN mkdir -p build

# set development environment variables
ENV CMAKE_BUILD_TYPE=Debug
ENV OMP_NUM_THREADS=8

CMD ["/bin/bash"]
73 changes: 73 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Docker Support
__Run DEM-Engine in a containerized environment__

## Quick start
Make sure to initialize the submodule before using image.

```
git submodule init
git submodule update
```

DEM-Engine provides Docker images for both development and production use:

<li><strong>Production Image</strong>: Optimized runtime environment with pre-built binaries</li>

<li><strong>Development Image</strong>: Full build environment with debugging tools</li>

```
# Build and run the production image
docker-compose -f .devcontainer/docker-compose.yml up deme-production

# Or start a development environment
docker-compose -f .devcontainer/docker-compose.yml run --rm deme-dev
```

## Tips
### Customize output directory & demo
There are two ways to customize the output directory and demo execution:

#### 1. Modify docker-compose.yml
Edit the `docker-compose.yml` file to change default settings:
```
volumes:
- ../output:/workspace/DEM-Engine/build/output # change this line to your desired output directory
command: ["/workspace/DEM-Engine/build/bin/DEMdemo_Mixer"] # replace with your production command
```
#### 2. Override via Command Line
Use command-line overrides for more flexibility without modifying files:

```
# Run specific demos by overriding the command
docker-compose -f .devcontainer/docker-compose.yml run --rm deme-production \
/workspace/DEM-Engine/build/bin/DEMdemo_BallDrop

# Run with custom output directory
docker-compose -f .devcontainer/docker-compose.yml run --rm \
-v $(pwd)/my_output:/workspace/DEM-Engine/build/output \
deme-production /workspace/DEM-Engine/build/bin/DEMdemo_RotatingDrum

# Run with both custom output directory AND specific demo
docker-compose -f .devcontainer/docker-compose.yml run --rm \
-v $(pwd)/results/experiment1:/workspace/DEM-Engine/build/output \
deme-production /workspace/DEM-Engine/build/bin/DEMdemo_ConePenetration
```

### Organizing output files

Based on the current mount configuration, consider using nested directories in your demo scripts for better organization:

```
path out_dir = current_path() / "output" / "DemoOutput_Mixer";
```

## Volume Mounts
The development container uses several volumes for persistence:

<li><strong>deme-build-cache</strong>: Caches build artifacts</li>
<li><strong>deme-ccache</strong>: Compiler cache for faster rebuilds</li>
<li><strong>deme-vscode-extensions</strong>: VSCode extensions</li>




127 changes: 127 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"name": "DEM-Engine Development",
"dockerComposeFile": "docker-compose.yml",
"service": "deme-dev",
"workspaceFolder": "/workspace/DEM-Engine",

"features": {
// Only essential features
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true,
"installOhMyZsh": true,
"upgradePackages": false
}
},

"customizations": {
"vscode": {
"extensions": [
// C++ development
"ms-vscode.cpptools",
"ms-vscode.cpptools-extension-pack",
"ms-vscode.cmake-tools",
"ms-vscode.makefile-tools",

// CUDA support
"nvidia.nsight-vscode-edition",

// Python support
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.debugpy",

// Docker support
"ms-azuretools.vscode-docker",

// Visualization
"echatroner.rainbow-csv"
],

"settings": {
// Terminal
"terminal.integrated.defaultProfile.linux": "zsh",

// CMake - optimized for DEM-Engine
"cmake.configureOnOpen": false, // Manual control
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.generator": "Ninja",
"cmake.configureArgs": [
"-DCMAKE_BUILD_TYPE=${env:CMAKE_BUILD_TYPE}",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
"-DCMAKE_CUDA_ARCHITECTURES=native" // Auto-detect GPU
],
"cmake.parallelJobs": 0, // Use all cores

// C++
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.formatting": "clangFormat",
"C_Cpp.autocompleteAddParentheses": true,

// File associations
"files.associations": {
"*.cu": "cuda-cpp",
"*.cuh": "cuda-cpp"
},

// Python
"python.defaultInterpreterPath": "/usr/bin/python3",

// Editor
"editor.formatOnSave": false, // Only format manually
"editor.rulers": [100], // Single ruler at 100
"editor.minimap.enabled": false, // Save screen space

// Performance optimizations
"files.watcherExclude": {
"**/build/**": true,
"**/output/**": true,
"**/.git/**": true,
"**/thirdparty/**": true
},

"search.exclude": {
"**/build": true,
"**/output": true,
"**/thirdparty": true,
"**/*.o": true,
"**/*.so": true
},

// Disable telemetry for privacy
"telemetry.telemetryLevel": "off"
}
}
},

// Optimized mounts - only essential ones
"mounts": [
// Cache build artifacts
"source=deme-build-cache,target=/workspace/DEM-Engine/build,type=volume",
// Persist extensions
"source=deme-vscode-extensions,target=/root/.vscode-server/extensions,type=volume"
],

// Simplified lifecycle commands
"postCreateCommand": "echo '🚀 DEM-Engine Dev Environment Ready' && nvcc --version",

"postStartCommand": "git config --global --add safe.directory /workspace/DEM-Engine",

// Only forward ports you actually use
"forwardPorts": [],

// Environment variables
"containerEnv": {
"CUDA_VISIBLE_DEVICES": "all",
"NVIDIA_DRIVER_CAPABILITIES": "all"
},

"remoteUser": "root",

"remoteEnv": {
"CMAKE_BUILD_TYPE": "${localEnv:CMAKE_BUILD_TYPE:Debug}",
"OMP_NUM_THREADS": "${localEnv:OMP_NUM_THREADS:8}",
"CUDA_LAUNCH_BLOCKING": "${localEnv:CUDA_LAUNCH_BLOCKING:0}"
}
}
Loading