Skip to content

samslaves/fortran-container

Repository files navigation

Fortran Development Environment with Podman

Complete Fortran development environment with automatic permission handling - no manual permission fixes needed!

✨ Key Features

  • 🔒 Automatic Permissions - No manual chmod or chown needed!
  • 🚀 gfortran - GNU Fortran compiler with F77/F90/F95/F2003/F2008/F2018 support
  • 📦 FPM - Modern Fortran Package Manager
  • 🧮 Scientific Libraries - BLAS, LAPACK, NetCDF, HDF5, OpenMPI
  • 🛠️ Build Tools - Make, CMake, Ninja
  • 🐛 Debugging - GDB, Valgrind
  • 🐍 Python Integration - NumPy, Matplotlib
  • 💻 VS Code Ready - SSH access for Remote Development
  • 👤 Non-root user - Safe development as fortrandev
  • 💾 Persistent workspace - Your projects are saved

🎯 How Permissions Work (Fully Automated!)

This setup uses automatic permission handling that works on all Linux distributions:

  1. podman unshare - Fixes ownership before container starts
  2. :z flag - Handles SELinux labels (Fedora/RHEL) and is safely ignored on Ubuntu/Debian
  3. Entrypoint script - Fixes permissions inside container on startup

Works automatically on:

  • ✅ Fedora (with SELinux)
  • ✅ Ubuntu/Debian (no SELinux)
  • ✅ RHEL/CentOS (with SELinux)
  • ✅ Any Linux distribution with Podman

You don't need to run chmod, chown, setenforce, or any permission commands!

📋 Prerequisites

  • Podman installed
  • (Optional) podman-compose
  • VS Code with Remote-SSH extension (for IDE access)

🚀 Quick Start (3 Steps)

Step 1: Build the Container

chmod +x podman-manage.sh
./podman-manage.sh build

Step 2: Start the Container

./podman-manage.sh start

Step 3: Verify Everything Works

./podman-manage.sh test

You should see:

✓ SSH connection successful
✓ Workspace is writable
✓ Fortran compilation works
✓ All tests passed!

📟 Understanding the Podman Run Command

Complete Command Breakdown

The podman-manage.sh start command executes this:

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

Parameter Explanation

Parameter Description Purpose
podman run Create and start a new container Base command to run containers
-d Detached mode - Run in background Container runs as daemon, terminal is free
--name fortran-dev-container Container name - Identifier Reference container easily: podman stop fortran-dev-container
-p 2223:22 Port mapping - Host:Container SSH access: ssh user@localhost -p 2223 → container port 22
-v ./fortran-projects:/home/fortrandev/workspace:U Volume mount - Host:Container:Flags Projects in ./fortran-projects/home/fortrandev/workspace
--hostname fortran-dev Hostname - Container's hostname Sets hostname command output inside container
fortran-dev Image name - Image to use Must match name from podman build -t fortran-dev .

Volume Mount Flags Explained

The :U flag is critical for automatic permission handling:

Flag Description When to Use
:U Auto-chown - Sets ownership to match container user ✅ Recommended - Our default, fixes permissions automatically
:z Shared SELinux label - Multiple containers can access Shared data between containers
:Z Private SELinux label - Exclusive to this container Isolated, private data
:ro Read-only - Container cannot modify Protect source code from modifications
:rw Read-write - Container can modify (default) Normal development, allows file creation/editing

Common Variations

Custom Workspace Path

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v /home/samuele/MyFortranCode:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

Different SSH Port

podman run -d \
    --name fortran-dev-container \
    -p 2225:22 \  # Changed host port to 2225
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

# Connect with: ssh fortrandev@localhost -p 2225

Read-Only Workspace

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:ro \  # Read-only
    --hostname fortran-dev \
    fortran-dev

Multiple Volumes (Data + Libraries)

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    -v ./simulation-data:/home/fortrandev/data:U \  # Simulation data
    -v ./shared-libs:/home/fortrandev/libs:ro \  # Read-only libraries
    --hostname fortran-dev \
    fortran-dev

With Resource Limits

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --memory=4g \  # Limit RAM to 4GB (useful for simulations)
    --cpus=4 \  # Limit to 4 CPU cores
    fortran-dev

Interactive Mode (No Background)

podman run -it \  # -i = interactive, -t = terminal (not -d)
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev \
    /bin/bash  # Start with bash shell

For MPI Applications (Shared Memory)

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --shm-size=2g \  # Increase shared memory for MPI
    fortran-dev

Manual Start (Without Script)

If you prefer not to use podman-manage.sh:

# 1. Build image
podman build -t fortran-dev .

# 2. Create projects directory
mkdir -p fortran-projects

# 3. Run container
podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

# 4. Verify it's running
podman ps

# 5. Connect
ssh fortrandev@localhost -p 2223
# Password: fortran

Troubleshooting Run Command

Port Already in Use

# Error: address already in use
# Solution: Use different port or stop conflicting service
podman run -d \
    --name fortran-dev-container \
    -p 2225:22 \  # Changed to 2225
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

# Connect with: ssh fortrandev@localhost -p 2225

Container Name Conflict

# Error: the container name "fortran-dev-container" is already in use
# Solution 1: Remove old container
podman rm -f fortran-dev-container

# Solution 2: Use different name
podman run -d \
    --name fortran-dev-2 \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

Volume Path Not Found

# Error: no such file or directory
# Solution: Use absolute path or create directory
mkdir -p ./fortran-projects

# Or use absolute path
podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v /home/samuele/fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    fortran-dev

Image Not Found

# Error: image not known
# Solution: Build image first
podman build -t fortran-dev .

# Then run
podman run -d --name fortran-dev-container ...

Compilation Errors (Permission Issues)

# If you still see permission errors during compilation
# Verify :U flag is present
podman inspect fortran-dev-container | grep -A 5 Mounts

# Should show: "Options": ["U"]

Advanced Options

Environment Variables

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    -e OMP_NUM_THREADS=4 \  # OpenMP threads
    -e FORT_FMT_RECL=1024 \  # Fortran format record length
    --hostname fortran-dev \
    fortran-dev

Custom DNS

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --dns 8.8.8.8 \  # Google DNS
    --dns 8.8.4.4 \
    --hostname fortran-dev \
    fortran-dev

Privileged Mode (for Hardware Access)

# WARNING: Less secure, use only if needed for hardware access
podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --privileged \  # Full access to host devices
    fortran-dev

With GPU Support (if available)

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --device nvidia.com/gpu=all \  # All GPUs
    fortran-dev

Restart Policy

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --restart unless-stopped \  # Auto-restart on boot
    fortran-dev

Ulimit Settings (for Large Simulations)

podman run -d \
    --name fortran-dev-container \
    -p 2223:22 \
    -v ./fortran-projects:/home/fortrandev/workspace:U \
    --hostname fortran-dev \
    --ulimit nofile=65535:65535 \  # Increase open files limit
    --ulimit nproc=4096:4096 \  # Increase process limit
    fortran-dev

Quick Reference

# Standard run
podman run -d --name fortran-dev-container -p 2223:22 \
  -v ./fortran-projects:/home/fortrandev/workspace:U \
  --hostname fortran-dev fortran-dev

# Custom path
podman run -d --name fortran-dev-container -p 2223:22 \
  -v /my/path:/home/fortrandev/workspace:U \
  --hostname fortran-dev fortran-dev

# Different port
podman run -d --name fortran-dev-container -p 2225:22 \
  -v ./fortran-projects:/home/fortrandev/workspace:U \
  --hostname fortran-dev fortran-dev

# With limits (for heavy simulations)
podman run -d --name fortran-dev-container -p 2223:22 \
  -v ./fortran-projects:/home/fortrandev/workspace:U \
  --memory=8g --cpus=8 --shm-size=4g \
  --hostname fortran-dev fortran-dev

# Interactive
podman run -it --name fortran-dev-container -p 2223:22 \
  -v ./fortran-projects:/home/fortrandev/workspace:U \
  --hostname fortran-dev fortran-dev /bin/bash

# For MPI simulations
podman run -d --name fortran-dev-container -p 2223:22 \
  -v ./fortran-projects:/home/fortrandev/workspace:U \
  --shm-size=2g --hostname fortran-dev fortran-dev

Scientific Computing Examples

Plasma Physics Simulation

podman run -d \
    --name plasma-sim \
    -p 2223:22 \
    -v ~/Simulations/Plasma:/home/fortrandev/workspace:U \
    -v ~/Data/Plasma:/home/fortrandev/data:U \
    --memory=16g \
    --cpus=8 \
    --shm-size=4g \
    --hostname fortran-dev \
    fortran-dev

Quantum Mechanics Calculations

podman run -d \
    --name quantum-calc \
    -p 2223:22 \
    -v ~/Teaching/QuantumMechanics:/home/fortrandev/workspace:U \
    --memory=4g \
    --cpus=4 \
    --hostname fortran-dev \
    fortran-dev

🔌 Connect from VS Code

1. Install Remote-SSH Extension

  • Open VS Code
  • Install "Remote - SSH" extension by Microsoft

2. Add SSH Host

  • Press F1 → "Remote-SSH: Add New SSH Host"
  • Enter: ssh fortrandev@localhost -p 2223
  • Choose config file (usually first option)

3. Connect

  • Press F1 → "Remote-SSH: Connect to Host"
  • Select localhost:2223
  • Password: fortran
  • Open folder: /home/fortrandev/workspace

That's it! No permission configuration needed.

🎓 Usage Examples

Basic Compilation

# SSH into container
ssh fortrandev@localhost -p 2223
# Password: fortran

# Go to workspace
cd ~/workspace

# Create a Fortran file
cat > hello.f90 << 'EOF'
program hello
    implicit none
    print *, "Hello from Fortran!"
end program hello
EOF

# Compile
gfortran hello.f90 -o hello

# Run
./hello

Quick Compile & Run

# Use the built-in alias
frun hello.f90

With Optimization

# Debug mode
gfortran $FFLAGS_DEBUG -o debug.out myprogram.f90

# Optimized mode
gfortran $FFLAGS_OPT -o optimized.out myprogram.f90

Modern Project with FPM

cd ~/workspace

# Create new project
fpm new my-project
cd my-project

# Edit your code in app/main.f90 and src/

# Build
fpm build

# Run
fpm run

# Test
fpm test

Example structure:

my-project/
├── fpm.toml          # Project config
├── app/
│   └── main.f90      # Your main program
├── src/
│   └── my_lib.f90    # Your library
└── test/
    └── check.f90     # Unit tests

Using Makefile

# Copy template
cp ~/template.mk Makefile

# Edit to add your source files
nano Makefile

# Build
make

# Run
make run

# Clean
make clean

Scientific Computing with BLAS

program matrix_multiply
    implicit none
    integer, parameter :: n = 3
    real(8) :: A(n,n), B(n,n), C(n,n)
    
    ! Initialize
    A = reshape([1.0d0, 2.0d0, 3.0d0, &
                 4.0d0, 5.0d0, 6.0d0, &
                 7.0d0, 8.0d0, 9.0d0], [n,n])
    B = reshape([9.0d0, 8.0d0, 7.0d0, &
                 6.0d0, 5.0d0, 4.0d0, &
                 3.0d0, 2.0d0, 1.0d0], [n,n])
    
    ! Matrix multiply with BLAS
    call dgemm('N', 'N', n, n, n, 1.0d0, A, n, B, n, 0.0d0, C, n)
    
    print *, 'Result:', C
end program matrix_multiply

Compile with BLAS:

gfortran matrix_multiply.f90 -lblas -o matmul
./matmul

Parallel Computing with MPI

program mpi_hello
    use mpi
    implicit none
    integer :: ierr, rank, size
    
    call MPI_Init(ierr)
    call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
    call MPI_Comm_size(MPI_COMM_WORLD, size, ierr)
    
    print *, 'Hello from rank', rank, 'of', size
    
    call MPI_Finalize(ierr)
end program mpi_hello

Compile and run:

mpif90 mpi_hello.f90 -o mpi_hello
mpirun -np 4 ./mpi_hello

🛠️ Management Commands

./podman-manage.sh build     # Build the image
./podman-manage.sh start     # Start container
./podman-manage.sh stop      # Stop container
./podman-manage.sh restart   # Restart container
./podman-manage.sh remove    # Remove container
./podman-manage.sh rebuild   # Rebuild everything
./podman-manage.sh logs      # View logs
./podman-manage.sh shell     # Open shell in container
./podman-manage.sh status    # Show status
./podman-manage.sh cleanup   # Force cleanup
./podman-manage.sh test      # Test environment

🔧 Alternative: Using podman-compose

# Install podman-compose if needed
pip3 install podman-compose

# Start
podman-compose up -d

# Stop
podman-compose down

# Rebuild
podman-compose up -d --build

🧪 Debugging

With GDB

# Compile with debug symbols
gfortran -g -fbacktrace myprogram.f90 -o debug.out

# Run debugger
gdb ./debug.out

# GDB commands
(gdb) run
(gdb) break main
(gdb) next
(gdb) print variable
(gdb) quit

With Valgrind

# Check memory leaks
valgrind --leak-check=full ./myprogram

# Check bounds
valgrind --track-origins=yes ./myprogram

📚 Recommended VS Code Extensions

Install these after connecting via Remote-SSH:

  1. Modern Fortran (fortran-lang.linter-gfortran)
  2. C/C++ (includes Fortran debugging)
  3. Code Runner

Install Fortran Language Server in container:

pip3 install fortls

⚙️ Default Credentials

  • Username: fortrandev
  • Password: fortran
  • SSH Port: 2223

⚠️ Change for production use!

🔬 What's Included

Compilers & Tools

  • gfortran (GNU Fortran)
  • gcc, g++
  • make, cmake, ninja
  • FPM (Fortran Package Manager)
  • GDB, Valgrind

Scientific Libraries

  • BLAS (Basic Linear Algebra)
  • LAPACK (Linear Algebra Package)
  • OpenMPI (Parallel computing)
  • NetCDF (Scientific data)
  • HDF5 (Hierarchical data)

Python Tools

  • NumPy
  • Matplotlib

Editors

  • vim, nano

🆘 Troubleshooting

Container won't start - Port in use

./podman-manage.sh cleanup
./podman-manage.sh start

Can't SSH in

# Check container is running
./podman-manage.sh status

# View logs
./podman-manage.sh logs

# Try restart
./podman-manage.sh restart

Still having permission issues?

This shouldn't happen with the automatic setup, but if it does:

# Complete reset
./podman-manage.sh cleanup
rm -rf fortran-projects/
./podman-manage.sh start
./podman-manage.sh test

If test passes, everything is working!

Files look weird on host

This is normal with :U flag - files are owned by Podman's user namespace mapping. They're still fully accessible from both container and host for reading/writing.

🎯 Best Practices

  1. Create files inside the container (via SSH or VS Code Remote)
  2. Compile inside the container where all libraries are available
  3. Use FPM for modern Fortran project structure
  4. Version control - Use git inside the container
  5. Test regularly - Run ./podman-manage.sh test to verify environment

📖 Learning Resources

🔐 Security Notes

  • Default passwords are for development only
  • For production, change passwords in Dockerfile:
    RUN echo 'fortrandev:YOUR_PASSWORD' | chpasswd
  • Container runs as non-root user by default
  • Port 2223 only binds to localhost by default

💡 Tips & Tricks

Compile for maximum performance

gfortran -O3 -march=native -flto -fopenmp myprogram.f90

Profile your code

gfortran -pg myprogram.f90
./a.out
gprof a.out

Check compiler flags

gfortran --help

Pre-compile modules

gfortran -c module.f90       # Creates module.mod
gfortran -c main.f90          # Uses module.mod
gfortran -o program module.o main.o

📄 Files Structure

.
├── Dockerfile              # Container definition
├── podman-compose.yml      # Compose config
├── podman-manage.sh        # Management script
├── README.md              # This file
├── .gitignore             # Git ignore rules
└── fortran-projects/      # Your projects (auto-created)

🌟 Why This Setup is Better

No manual permission fixes - Everything is automatic ✅ Works immediately - No configuration needed ✅ Cross-platform - Works on any Linux with Podman ✅ VS Code ready - Perfect for modern development ✅ Complete toolkit - All tools you need included ✅ Isolated environment - Won't interfere with host system ✅ Easy to reset - ./podman-manage.sh rebuild for fresh start

🤝 Contributing

Found an issue or want to improve something? Feel free to modify and share!

📝 License

This configuration is provided as-is for development purposes.


Happy Fortran coding! 🚀

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors