devcontainer
docker
gazebo
gz
harmonic
vscode
Use Gazebo Harmonic with VS Code devcontainer
Use VS Code and Docker
Using Docker Compose
Using devcontainer to run Docker Compose
├── .devcontainer
│ ├── Dockerfile
│ └── devcontainer.json
├── docker-compose.yaml
├── env.sh
├── .gitignore
└── worlds
└── minimal.world
Download the complete project archive:
gz_harmonic_vscode.zip
Extract it and open the folder in VS Code:
unzip gz_harmonic_vscode.zip
cd gz_harmonic_vscode
code .
Dockerfile
FROM ubuntu:22.04 AS base
ENV DEBIAN_FRONTEND = noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
locales \
&& locale-gen en_US.UTF-8 \
&& update-locale LC_ALL = en_US.UTF-8 LANG = en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/*
ENV LANG = en_US.UTF-8
RUN ln -fs /usr/share/zoneinfo/UTC /etc/localtime \
&& apt-get update \
&& apt-get install -y --no-install-recommends tzdata \
&& dpkg-reconfigure --frontend noninteractive tzdata \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -q -y --no-install-recommends \
curl \
gnupg \
lsb-release \
python3-argcomplete \
sudo \
wget \
&& wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \
&& echo "deb [arch= $( dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $( lsb_release -cs) main" > /etc/apt/sources.list.d/gazebo-stable.list \
&& apt-get update \
&& apt-get install -y -q --no-install-recommends gz-harmonic \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update \
&& apt-get install -y -qq --no-install-recommends \
libglvnd0 \
libgl1 \
libglx0 \
libegl1 \
libxext6 \
libx11-6 \
&& rm -rf /var/lib/apt/lists/*
ENV NVIDIA_VISIBLE_DEVICES = all
ENV NVIDIA_DRIVER_CAPABILITIES = graphics,utility,compute
ENV QT_X11_NO_MITSHM = 1
ARG USERNAME = user
ARG USER_UID = 1000
ARG USER_GID = $USER_UID
RUN if getent passwd ubuntu > /dev/null 2 >& 1 ; then \
userdel -r ubuntu; \
fi \
&& groupadd --gid $USER_GID $USERNAME \
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME
RUN apt-get update \
&& apt-get install -y --no-install-recommends sudo \
&& echo " $USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update \
&& apt-get install -y -qq --no-install-recommends \
vim \
build-essential \
git \
openssh-client \
ca-certificates \
cmake \
&& rm -rf /var/lib/apt/lists/*
CMD [ "bash" ]
Docker Compose
docker-compose.yaml services :
gazebo :
build :
dockerfile : .devcontainer/Dockerfile
context : .
network_mode : host
user : user
stdin_open : true
tty : true
hostname : gz
working_dir : /workspace
environment :
- DISPLAY=${DISPLAY}
- QT_X11_NO_MITSHM=1
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
- __NV_PRIME_RENDER_OFFLOAD=1
- __GLX_VENDOR_LIBRARY_NAME=nvidia
- GZ_PARTITION=my_simulation
volumes :
- .:/workspace:cached
- ./.gz:/home/user/.gz:rw
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- /dev/dri:/dev/dri
- /dev/nvidia0:/dev/nvidia0
- /dev/nvidiactl:/dev/nvidiactl
- /dev/nvidia-modeset:/dev/nvidia-modeset
deploy :
resources :
reservations :
devices :
- capabilities : [ gpu ]
nvidia glx
__NV_PRIME_RENDER_OFFLOAD=1
__GLX_VENDOR_LIBRARY_NAME=nvidia
.devcontainer/devcontainer.json {
"name" : "gz_harmonic" ,
"dockerComposeFile" : "../docker-compose.yaml" ,
"service" : "gazebo" ,
"shutdownAction" : "stopCompose" ,
"workspaceFolder" : "/workspace" ,
"customizations" : {
"vscode" : {
"extensions" : [
"ms-python.python" ,
"ms-vscode.cpptools" ,
"redhat.vscode-xml" ,
"redhat.vscode-yaml" ,
"albert.tabout" ,
"actboy168.tasks" ,
"streetsidesoftware.code-spell-checker" ,
"ms-vscode.cmake-tools"
],
"settings" : {}
}
}
}
Run the simulation
Using Docker Compose
docker compose up --build -d
Then open a shell in the container:
docker compose exec gazebo bash
Run the world:
source env.sh
gz sim -v 4 -r worlds/minimal.world
Using Docker without Compose
Build the image:
docker build \
-t gz-harmonic-vscode \
-f .devcontainer/Dockerfile \
.
Allow local Docker containers to connect to the X server:
Run the container:
mkdir -p .gz
docker run \
--rm \
-it \
--name gz-harmonic \
--network host \
--hostname gz \
--user user \
--workdir /workspace \
--gpus all \
-e DISPLAY = " ${ DISPLAY } " \
-e QT_X11_NO_MITSHM = 1 \
-e NVIDIA_VISIBLE_DEVICES = all \
-e NVIDIA_DRIVER_CAPABILITIES = all \
-e __NV_PRIME_RENDER_OFFLOAD = 1 \
-e __GLX_VENDOR_LIBRARY_NAME = nvidia \
-e GZ_PARTITION = my_simulation \
-v " ${ PWD } :/workspace:rw" \
-v " ${ PWD } /.gz:/home/user/.gz:rw" \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
-v /dev/dri:/dev/dri \
--device /dev/nvidia0 \
--device /dev/nvidiactl \
--device /dev/nvidia-modeset \
gz-harmonic-vscode
Inside the container:
source env.sh
gz sim -v 4 -r worlds/minimal.world
minimal world
<?xml version="1.0"?>
<sdf version= "1.8" >
<world name= "world_demo" >
<physics name= "1ms" type= "ignored" >
<max_step_size> 0.001</max_step_size>
<real_time_factor> 1.0</real_time_factor>
</physics>
<plugin
filename= "gz-sim-physics-system"
name= "gz::sim::systems::Physics" >
</plugin>
<plugin
filename= "gz-sim-user-commands-system"
name= "gz::sim::systems::UserCommands" >
</plugin>
<plugin
filename= "gz-sim-scene-broadcaster-system"
name= "gz::sim::systems::SceneBroadcaster" >
</plugin>
<light type= "directional" name= "sun" >
<cast_shadows> true</cast_shadows>
<pose> 0 0 10 0 0 0</pose>
<diffuse> 0.8 0.8 0.8 1</diffuse>
<specular> 0.2 0.2 0.2 1</specular>
<attenuation>
<range> 1000</range>
<constant> 0.9</constant>
<linear> 0.01</linear>
<quadratic> 0.001</quadratic>
</attenuation>
<direction> -0.5 0.1 -0.9</direction>
</light>
<model name= "ground_plane" >
<static> true</static>
<link name= "link" >
<collision name= "collision" >
<geometry>
<plane>
<normal> 0 0 1</normal>
<size> 100 100</size>
</plane>
</geometry>
</collision>
<visual name= "visual" >
<geometry>
<plane>
<normal> 0 0 1</normal>
<size> 100 100</size>
</plane>
</geometry>
<material>
<ambient> 0.8 0.8 0.8 1</ambient>
<diffuse> 0.8 0.8 0.8 1</diffuse>
<specular> 0.8 0.8 0.8 1</specular>
</material>
</visual>
</link>
</model>
</world>
</sdf>
Environment helper file
Change prompt
Set Environment variables
Add keyboard shortcuts
env.sh export GZ_SIM_RESOURCE_PATH = " $( pwd ) /models: $( pwd ) /worlds: ${ GZ_SIM_RESOURCE_PATH } "
export GZ_SIM_SYSTEM_PLUGIN_PATH = " $( pwd ) /bin: ${ GZ_SIM_SYSTEM_PLUGIN_PATH } "
bind '"\C-b": "gz sim -v 4 -r worlds/minimal.world"'
parse_git_branch() {
git branch 2 > /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/'
}
export PS1 = "gz \[\033[32m\]\u@\h\[\033[00m\]:\[\033[34m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\]\$ "
echo "Gazebo Harmonic environment ready"
Usage
# run the simulation
gz sim -v 4 -r worlds/minimal.world
gz topic gz topic --list
gz topic -e -t /clock
#
sim {
sec: 326
nsec: 476000000
}
Gz Transport
gz_transport is Gazebo's communication middleware, used for inter-process communication (IPC) between different Gazebo components — like sensors, plugins, UI, and even ROS bridges.
GZ_PARTITION : Isolates topic namespaces between different simulations
GZ_DISCOVERY_SERVER : IP address of the main discovery server (usually the Gazebo server machine)
GZ_TRANSPORT_IP : IP address the local process uses to advertise itself to others
Resource