Complete Fortran development environment with automatic permission handling - no manual permission fixes needed!
- 🔒 Automatic Permissions - No manual
chmodorchownneeded! - 🚀 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
This setup uses automatic permission handling that works on all Linux distributions:
- podman unshare - Fixes ownership before container starts
- :z flag - Handles SELinux labels (Fedora/RHEL) and is safely ignored on Ubuntu/Debian
- 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!
- Podman installed
- (Optional) podman-compose
- VS Code with Remote-SSH extension (for IDE access)
chmod +x podman-manage.sh
./podman-manage.sh build./podman-manage.sh start./podman-manage.sh testYou should see:
✓ SSH connection successful
✓ Workspace is writable
✓ Fortran compilation works
✓ All tests passed!
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 | 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 . |
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 |
podman run -d \
--name fortran-dev-container \
-p 2223:22 \
-v /home/samuele/MyFortranCode:/home/fortrandev/workspace:U \
--hostname fortran-dev \
fortran-devpodman 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 2225podman run -d \
--name fortran-dev-container \
-p 2223:22 \
-v ./fortran-projects:/home/fortrandev/workspace:ro \ # Read-only
--hostname fortran-dev \
fortran-devpodman 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-devpodman 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-devpodman 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 shellpodman 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-devIf 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# 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# 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# 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# Error: image not known
# Solution: Build image first
podman build -t fortran-dev .
# Then run
podman run -d --name fortran-dev-container ...# 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"]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-devpodman 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# 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-devpodman 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-devpodman 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-devpodman 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# 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-devpodman 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-devpodman run -d \
--name quantum-calc \
-p 2223:22 \
-v ~/Teaching/QuantumMechanics:/home/fortrandev/workspace:U \
--memory=4g \
--cpus=4 \
--hostname fortran-dev \
fortran-dev- Open VS Code
- Install "Remote - SSH" extension by Microsoft
- Press
F1→ "Remote-SSH: Add New SSH Host" - Enter:
ssh fortrandev@localhost -p 2223 - Choose config file (usually first option)
- Press
F1→ "Remote-SSH: Connect to Host" - Select
localhost:2223 - Password:
fortran - Open folder:
/home/fortrandev/workspace
That's it! No permission configuration needed.
# 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# Use the built-in alias
frun hello.f90# Debug mode
gfortran $FFLAGS_DEBUG -o debug.out myprogram.f90
# Optimized mode
gfortran $FFLAGS_OPT -o optimized.out myprogram.f90cd ~/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 testExample structure:
my-project/
├── fpm.toml # Project config
├── app/
│ └── main.f90 # Your main program
├── src/
│ └── my_lib.f90 # Your library
└── test/
└── check.f90 # Unit tests
# Copy template
cp ~/template.mk Makefile
# Edit to add your source files
nano Makefile
# Build
make
# Run
make run
# Clean
make cleanprogram 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_multiplyCompile with BLAS:
gfortran matrix_multiply.f90 -lblas -o matmul
./matmulprogram 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_helloCompile and run:
mpif90 mpi_hello.f90 -o mpi_hello
mpirun -np 4 ./mpi_hello./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# Install podman-compose if needed
pip3 install podman-compose
# Start
podman-compose up -d
# Stop
podman-compose down
# Rebuild
podman-compose up -d --build# 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# Check memory leaks
valgrind --leak-check=full ./myprogram
# Check bounds
valgrind --track-origins=yes ./myprogramInstall these after connecting via Remote-SSH:
- Modern Fortran (
fortran-lang.linter-gfortran) - C/C++ (includes Fortran debugging)
- Code Runner
Install Fortran Language Server in container:
pip3 install fortls- Username:
fortrandev - Password:
fortran - SSH Port:
2223
- gfortran (GNU Fortran)
- gcc, g++
- make, cmake, ninja
- FPM (Fortran Package Manager)
- GDB, Valgrind
- BLAS (Basic Linear Algebra)
- LAPACK (Linear Algebra Package)
- OpenMPI (Parallel computing)
- NetCDF (Scientific data)
- HDF5 (Hierarchical data)
- NumPy
- Matplotlib
- vim, nano
./podman-manage.sh cleanup
./podman-manage.sh start# Check container is running
./podman-manage.sh status
# View logs
./podman-manage.sh logs
# Try restart
./podman-manage.sh restartThis 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 testIf test passes, everything is working!
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.
- Create files inside the container (via SSH or VS Code Remote)
- Compile inside the container where all libraries are available
- Use FPM for modern Fortran project structure
- Version control - Use git inside the container
- Test regularly - Run
./podman-manage.sh testto verify environment
- Modern Fortran Tutorial
- GNU Fortran Manual
- FPM Documentation
- Fortran Wiki
- Practical Common Lisp Book - Free online
- 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
gfortran -O3 -march=native -flto -fopenmp myprogram.f90gfortran -pg myprogram.f90
./a.out
gprof a.outgfortran --helpgfortran -c module.f90 # Creates module.mod
gfortran -c main.f90 # Uses module.mod
gfortran -o program module.o main.o.
├── 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)
✅ 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
Found an issue or want to improve something? Feel free to modify and share!
This configuration is provided as-is for development purposes.
Happy Fortran coding! 🚀