diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index e6db6f85e..06c8da65c 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -13,37 +13,37 @@ RUN useradd -d /memristor -m \ echo "memristor ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers # Essentials -RUN apt-get update && apt-get install -y -o Dpkg::Options::="--force-overwrite" \ - ros-humble-navigation2 \ - ros-humble-nav2-bringup \ - ros-humble-rviz2 \ - ros-humble-teleop-twist-keyboard \ - ros-humble-dynamixel-sdk \ - ros-humble-can-msgs \ - ros-humble-ruckig \ - ros-humble-laser-filters \ - ros-humble-domain-bridge \ - ros-humble-rmw-cyclonedds-cpp \ - ros-humble-ros2-control \ - ros-humble-ros2-controllers \ - ros-humble-rqt-common-plugins \ - ros-humble-webots-ros2 \ - ros-humble-dynamixel-workbench-toolbox \ - ros-humble-behaviortree-cpp \ - libopencv-dev \ - python3-pip \ - python3-pil \ - alsa \ - libxshmfence1 \ - libgtk-3-dev \ - git \ - git-lfs \ - curl \ - wget \ - vim \ - rsync \ - dialog \ - fish +RUN apt-get update && apt-get install --no-install-recommends -y -o Dpkg::Options::="--force-overwrite" \ + ros-humble-navigation2 \ + ros-humble-nav2-bringup \ + ros-humble-rviz2 \ + ros-humble-teleop-twist-keyboard \ + ros-humble-dynamixel-sdk \ + ros-humble-can-msgs \ + ros-humble-ruckig \ + ros-humble-laser-filters \ + ros-humble-domain-bridge \ + ros-humble-rmw-cyclonedds-cpp \ + ros-humble-ros2-control \ + ros-humble-ros2-controllers \ + ros-humble-rqt-common-plugins \ + ros-humble-webots-ros2 \ + ros-humble-dynamixel-workbench-toolbox \ + ros-humble-behaviortree-cpp \ + libopencv-dev \ + python3-pip \ + python3-pil \ + alsa \ + libxshmfence1 \ + libgtk-3-dev \ + git \ + git-lfs \ + curl \ + wget \ + vim \ + rsync \ + dialog \ + fish @@ -57,7 +57,19 @@ RUN su memristor -c 'code --install-extension eamodio.gitlens' && \ su memristor -c 'code --install-extension ms-python.python' && \ su memristor -c 'code --install-extension ms-vscode.cpptools-extension-pack' && \ su memristor -c 'code --install-extension usernamehw.errorlens' && \ - su memristor -c 'code --install-extension redhat.vscode-xml' + su memristor -c 'code --install-extension redhat.vscode-xml' && \ + su memristor -c 'code --install-extension ms-iot.vscode-ros' + + + +# VS Code server +RUN su memristor -c 'curl -fsSL https://code-server.dev/install.sh | sh' && \ + su memristor -c 'code-server --install-extension eamodio.gitlens' && \ + su memristor -c 'code-server --install-extension ms-python.python' && \ + su memristor -c 'code-server --install-extension ms-vscode.cpptools-extension-pack' && \ + su memristor -c 'code-server --install-extension usernamehw.errorlens' && \ + su memristor -c 'code-server --install-extension redhat.vscode-xml' && \ + su memristor -c 'code-server --install-extension ms-iot.vscode-ros' # Webots RUN curl -L -o /tmp/webots.deb \ @@ -77,6 +89,7 @@ RUN wget -O /tmp/diff_drive_controller.deb http://snapshots.ros.org/humble/2022- COPY ./config/bashrc /tmp/bashrc COPY ./config/fish/. /memristor/.config/fish/ COPY ./config/starship.toml /memristor/.config/starship.toml +COPY ./config/vscode-server/config.yaml /memristor/.config/code-server/config.yaml COPY ./config/vscode/. /memristor/ros2_ws/.vscode/ COPY ./config/Cyberobotics/. /memristor/.config/Cyberbotics/ COPY --chmod=755 ./config/setup.sh /usr/bin/ @@ -88,3 +101,5 @@ RUN cat /tmp/bashrc >> /memristor/.bashrc && \ USER memristor WORKDIR /memristor/ros2_ws + +EXPOSE 31415 diff --git a/docker/Makefile b/docker/Makefile index 17bd32c0f..599d8d2e2 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -7,7 +7,7 @@ IMAGE=ghcr.io/memristor/mep3 .PHONY: all -all: destroy build run setup exec pull +all: destroy test-nvidia run setup-default exec start-code-server vnc: $(eval FLAVOR=vnc) @@ -15,6 +15,7 @@ vnc: @true run: + @${MAKE} -s test-nvidia @docker run \ --net=host \ --ipc=host \ @@ -31,6 +32,27 @@ run: -v ${PROJECT_DIR}:/memristor/ros2_ws/src/mep3:rw \ -d -it ${IMAGE} +test-nvidia: + $(eval NC=\033[1;0m) + $(eval RED=\033[1;31m) + $(eval GREEN=\033[1;32m) + + @lspci | grep -qi nvidia && base64 --decode massage | unxz || true + + @docker run --rm \ + -e NVIDIA_DRIVER_CAPABILITIES=all ${NVIDIA_GPU} \ + -e DISPLAY=${DISPLAY} \ + ${IMAGE} | grep -qi 'nvidia' && \ + printf '%b\n' "${RED}Detected NVIDIA GPU in system, but missing packets, look up NVIDIA GPU section in README!\n${NC}" || \ + printf '%b\n' "${GREEN}Everything set up!${NC}" + +start-code-server: + @docker exec -d -it mep3-${FLAVOR} bash -c 'pgrep code-server || code-server /memristor/ros2_ws/src/mep3' && \ + xdg-open 'localhost:31415?folder=/memristor/ros2_ws/src/mep3' + +stop-code-server: + @docker exec -it mep3-${FLAVOR} pkill -f code-server + exec: @docker exec -it mep3-${FLAVOR} bash @@ -38,7 +60,12 @@ destroy: @docker container kill mep3-${FLAVOR} || true @docker container rm -f mep3-${FLAVOR} || true -setup: - @docker exec -it mep3-${FLAVOR} /usr/bin/setup.sh +setup-default: + @docker exec -it mep3-${FLAVOR} sh -c '/usr/bin/setup.sh --all' + @echo 'Restarting mep3-${FLAVOR} container...' + @docker restart mep3-${FLAVOR} + +setup-interactive: + @docker exec -it mep3-${FLAVOR} sh -c '/usr/bin/setup.sh --all --interactive' @echo 'Restarting mep3-${FLAVOR} container...' @docker restart mep3-${FLAVOR} diff --git a/docker/README.md b/docker/README.md index 8c8029548..a1327d1a4 100644 --- a/docker/README.md +++ b/docker/README.md @@ -25,7 +25,10 @@ 5) _Optional:_ run container setup script ```sh - make setup + make setup-default + + # If you prefer to manually configure setup, you can just do make setup and go through the prompts + make setup-interactive ``` 6) Acces the environment from any terminal window ```sh @@ -33,6 +36,18 @@ ``` Graphical applications started inside this terminal will use your existing Xorg session to display. + +## Code Server +If you prefer to use browser based VS Code, you can start it in the container and then access it locally through your browser at `localhost:31415` + +```sh +# This will start the VS code server with your mep3 repo +make start-code-server + +# To stop the VS code server +make stop-code-server +``` + ## Remote development environment (VNC) @@ -48,3 +63,7 @@ and set `DISPLAY` environment variable on step 4 to its value (eg `:0`). ```sh export DISPLAY=:0 ``` + +## NVIDIA GPU +If you happen to have NVIDIA GPUs that you wish to use within these development environments, make sure +to have NVIDIA Container Toolkit installed on your system. More info, specific to your distribution [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html). diff --git a/docker/config/setup.sh b/docker/config/setup.sh index 000c34670..e701390a3 100755 --- a/docker/config/setup.sh +++ b/docker/config/setup.sh @@ -1,76 +1,208 @@ #!/usr/bin/env bash -if [ -z "${VENDOR}" ]; then - dialog --title 'mep3 setup' --default-item '2' --menu 'Setup script vendor:' 0 0 0 1 'Docker image' 2 'Active git branch' 2>/tmp/answer - if grep -q '^2$' /tmp/answer; then - VENDOR=1 exec /memristor/ros2_ws/src/mep3/docker/config/setup.sh - exit - fi -else - commit="$(cd /memristor/ros2_ws/src/mep3 && git rev-parse --short HEAD)" - dialog --msgbox "Using staging setup script (${commit})" 5 42 -fi +_help=false +_configure_proxy=false +_vnc=false +_first_time_ros_setup=false +_enhanced_shell_prompt=false +_shell_shortcuts=false +_all=false +interactive=false -if dialog --title 'mep3 config' --defaultno --yesno 'Enable UNS proxy' 5 30; then - sed '/# Setup_proxy/d' -i /memristor/.bashrc - sudo sed '/# Setup_proxy/d' -i /etc/apt/apt.conf - echo "source /memristor/ros2_ws/src/mep3/docker/config/proxy.sh &>/dev/null # Setup_proxy" >> /memristor/.bashrc - source /memristor/ros2_ws/src/mep3/docker/config/proxy.sh - echo 'Acquire::http::Proxy "http://ftn.proxy:8080"; # Setup_proxy' | sudo tee -a /etc/apt/apt.conf - echo 'Acquire::https::Proxy "https://ftn.proxy:8080"; # Setup_proxy' | sudo tee -a /etc/apt/apt.conf -else - sed '/# Setup_proxy/d' -i /memristor/.bashrc - sudo sed '/# Setup_proxy/d' -i /etc/apt/apt.conf -fi +usage() { + echo "Usage: $0 [--help] [--configure-proxy] [--vnc] [--first-time-ros-setup] [--enhanced-shell-prompt] [--shell-shortcuts] [--interactive]" + echo "--help print help and exit" + echo "--interactive do everything interactively" + echo "--no-default do not use default setup configurations" + echo "--configure-proxy configures proxy for use in ftn network" + echo "--vnc configures VNC server in the container for outside remote DE use" + echo "--first-time-ros-setup configures ros for the first time setup" + echo "--enhanced-shell-prompt enables starship enhanced shell prompt" + echo "--shell-shortcuts enables shell shortcuts for easier tools use" + exit +} -if dialog --title 'mep3 config' --yesno 'Run first time ROS setup' 5 30; then - clear - sudo -E rosdep init - sudo -E apt-get install -y python3-vcstool - rosdep --rosdistro "${ROS_DISTRO}" update - cd /memristor/ros2_ws && yes | rosdep --rosdistro "${ROS_DISTRO}" install -r --from-paths src --ignore-src -fi +default_configure_proxy() { + sed '/# Setup_proxy/d' -i /memristor/.bashrc + sudo sed '/# Setup_proxy/d' -i /etc/apt/apt.conf +} -if dialog --title 'mep3 config' --yesno 'Enable enhanced shell prompt' 5 38; then - sed '/# Setup_prompt/d' -i /memristor/.config/fish/config.fish - echo 'starship init fish | source # Setup_prompt' >> /memristor/.config/fish/config.fish - eval "curl -sS https://starship.rs/install.sh | sh -s -- --yes" -else - sed '/# Setup_prompt/d' -i /memristor/.config/fish/config.fish -fi +configure_proxy() { + if $interactive; then + # FTN proxy is actually enabled here + if dialog --title 'mep3 config' --defaultno --yesno 'Enable UNS proxy' 5 30; then + sed '/# Setup_proxy/d' -i /memristor/.bashrc + sudo sed '/# Setup_proxy/d' -i /etc/apt/apt.conf + echo "source /memristor/ros2_ws/src/mep3/docker/config/proxy.sh &>/dev/null # Setup_proxy" >>/memristor/.bashrc + source /memristor/ros2_ws/src/mep3/docker/config/proxy.sh + echo 'Acquire::http::Proxy "http://ftn.proxy:8080"; # Setup_proxy' | sudo tee -a /etc/apt/apt.conf + echo 'Acquire::https::Proxy "https://ftn.proxy:8080"; # Setup_proxy' | sudo tee -a /etc/apt/apt.conf + return + fi + fi + default_configure_proxy +} -if dialog --title 'mep3 config' --yesno 'Enable shell shortcuts' 5 30; then - sed '/# Setup_shortcuts/d' -i /memristor/.config/fish/config.fish - echo "source /memristor/ros2_ws/src/mep3/docker/config/fish/shortcuts.fish &>/dev/null # Setup_shortcuts" >> /memristor/.config/fish/config.fish - echo "source /memristor/ros2_ws/src/mep3/docker/config/fish/git.fish &>/dev/null # Setup_shortcuts" >> /memristor/.config/fish/config.fish - dialog --msgbox 'Type "h" into terminal to list all mep3 shortcuts' 5 53 -else - sed '/# Setup_shortcuts/d' -i /memristor/.config/fish/config.fish -fi +default_first_time_ros_setup() { + clear + sudo -E rosdep init + sudo -E apt-get install -y python3-vcstool + rosdep --rosdistro "${ROS_DISTRO}" update + cd /memristor/ros2_ws && yes | rosdep --rosdistro "${ROS_DISTRO}" install -r --from-paths src --ignore-src +} -if test -f /opt/TurboVNC/bin/vncserver; then - if dialog --title 'mep3 config' --yesno 'Enable VNC' 5 30; then - VNC_CMD='/usr/bin/vnc.sh &>/dev/null' - if dialog --title 'mep3 config' --yesno 'Enable GPU acceleration' 5 30; then - VNC_CMD="VGL=-vgl ${VNC_CMD}" - fi - if dialog --title 'mep3 config' --inputbox 'Enter host X11 display server location' 8 30 "$DISPLAY" 2>/tmp/answer; then - VNC_CMD=" DISPLAY=$(cat /tmp/answer) ${VNC_CMD}" - fi - if dialog --title 'mep3 config' --inputbox 'Enter VNC server port' 8 30 5910 2>/tmp/answer; then - VNC_CMD=" PORT_VNC=$(cat /tmp/answer) ${VNC_CMD}" - fi - if dialog --title 'mep3 config' --inputbox 'Enter noVNC webserver port' 8 30 6810 2>/tmp/answer; then - VNC_CMD=" PORT_WEB=$(cat /tmp/answer) ${VNC_CMD}" - fi - sed '/# Setup_VNC/d' -i /memristor/.bashrc - echo "$VNC_CMD # Setup_VNC" >> /memristor/.bashrc - else - sed '/# Setup_VNC/d' -i /memristor/.bashrc - fi -fi +first_time_ros_setup() { + if $interactive; then + if dialog --title 'mep3 config' --yesno 'Run first time ROS setup' 5 30; then + default_first_time_ros_setup + return + fi + fi + default_first_time_ros_setup +} + +default_enhanced_shell_prompt() { + sed '/# Setup_prompt/d' -i /memristor/.config/fish/config.fish + echo 'starship init fish | source # Setup_prompt' >>/memristor/.config/fish/config.fish + eval "curl -sS https://starship.rs/install.sh | sh -s -- --yes" +} + +enhanced_shell_prompt() { + if $interactive; then + if dialog --title 'mep3 config' --yesno 'Enable enhanced shell prompt' 5 38; then + default_enhanced_shell_prompt + return + else + sed '/# Setup_prompt/d' -i /memristor/.config/fish/config.fish + fi + fi + default_enhanced_shell_prompt +} -sed '/# Setup_shell/d' -i /memristor/.bashrc -echo 'echo "$-" | grep i -q && exec fish # Setup_shell' >> /memristor/.bashrc +default_shell_shortcuts() { + sed '/# Setup_shortcuts/d' -i /memristor/.config/fish/config.fish + echo "source /memristor/ros2_ws/src/mep3/docker/config/fish/shortcuts.fish &>/dev/null # Setup_shortcuts" >>/memristor/.config/fish/config.fish + echo "source /memristor/ros2_ws/src/mep3/docker/config/fish/git.fish &>/dev/null # Setup_shortcuts" >>/memristor/.config/fish/config.fish +} -clear +shell_shortcuts() { + if $interactive; then + if dialog --title 'mep3 config' --yesno 'Enable shell shortcuts' 5 30; then + default_shell_shortcuts + return + else + sed '/# Setup_shortcuts/d' -i /memristor/.config/fish/config.fish + fi + fi + default_shell_shortcuts +} + +interactive_vnc() { + if dialog --title 'mep3 config' --yesno 'Enable VNC' 5 30; then + VNC_CMD='/usr/bin/vnc.sh &>/dev/null' + if dialog --title 'mep3 config' --yesno 'Enable GPU acceleration' 5 30; then + VNC_CMD="VGL=-vgl ${VNC_CMD}" + fi + if dialog --title 'mep3 config' --inputbox 'Enter host X11 display server location' 8 30 "$DISPLAY" 2>/tmp/answer; then + VNC_CMD=" DISPLAY=$(cat /tmp/answer) ${VNC_CMD}" + fi + if dialog --title 'mep3 config' --inputbox 'Enter VNC server port' 8 30 5910 2>/tmp/answer; then + VNC_CMD=" PORT_VNC=$(cat /tmp/answer) ${VNC_CMD}" + fi + if dialog --title 'mep3 config' --inputbox 'Enter noVNC webserver port' 8 30 6810 2>/tmp/answer; then + VNC_CMD=" PORT_WEB=$(cat /tmp/answer) ${VNC_CMD}" + fi + sed '/# Setup_VNC/d' -i /memristor/.bashrc + echo "$VNC_CMD # Setup_VNC" >>/memristor/.bashrc + else + sed '/# Setup_VNC/d' -i /memristor/.bashrc + fi +} + +default_vnc() { + VNC_CMD='/usr/bin/vnc.sh &>/dev/null' + VNC_CMD="VGL=-vgl DISPLAY=$DISPLAY PORT_VNC=5910 PORT_WEB=6810 ${VNC_CMD}" + sed '/# Setup_VNC/d' -i /memristor/.bashrc + echo "$VNC_CMD # Setup_VNC" >>/memristor/.bashrc +} + +vnc() { + if test -f /opt/TurboVNC/bin/vncserver; then + echo "TurboVNC is not installed" + exit 1 + fi + if $interactive; then + interactive_vnc + return + fi + default_vnc +} + +finalize() { + sed '/# Setup_shell/d' -i /memristor/.bashrc + echo 'echo "$-" | grep i -q && exec fish # Setup_shell' >>/memristor/.bashrc + + clear +} + +while [ "$#" -gt 0 ]; do + case "$1" in + --configure-proxy) + _configure_proxy=true + ;; + --vnc) + _vnc=true + ;; + --first-time-ros-setup) + _first_time_ros_setup=true + ;; + --enhanced-shell-prompt) + _enhanced_shell_prompt=true + ;; + --shell-shortcuts) + _shell_shortcuts=true + ;; + --interactive) + interactive=true + ;; + --help) + _help=true + ;; + --all) + _all=true + ;; + *) + usage + ;; + esac + shift +done + +if $_help; then + usage +fi + +if $_all; then + configure_proxy + first_time_ros_setup + enhanced_shell_prompt + shell_shortcuts + vnc +else + if $_configure_proxy; then + configure_proxy + fi + if $_first_time_ros_setup; then + first_time_ros_setup + fi + if $_enhanced_shell_prompt; then + enhanced_shell_prompt + fi + if $_shell_shortcuts; then + shell_shortcuts + fi + if $_vnc; then + vnc + fi +fi +finalize diff --git a/docker/config/vscode-server/config.yaml b/docker/config/vscode-server/config.yaml new file mode 100644 index 000000000..f422467e1 --- /dev/null +++ b/docker/config/vscode-server/config.yaml @@ -0,0 +1,3 @@ +bind-addr: 0.0.0.0:31415 +auth: none +cert: false diff --git a/docker/massage b/docker/massage new file mode 100644 index 000000000..2fa1e29c0 --- /dev/null +++ b/docker/massage @@ -0,0 +1,21 @@ +/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AhtBDhdACSICuaTlpBbGyQavVQi+uHevPuEtoNXgL1+ +4e7IDmpqCeHPKzFS2eYdY9NljF/D4ZQXNVpS0Oa2C3E0YUhUjOM574MAJ2EgtuVprBjSnhokyeTH +Vt534cSgR6u3VDYfevstpfhtEr7j07IjN4Re64x0zqlEiMM9mo3B92pwRSU/nnMbtVuf+pt9f4pi +UZpvVeDB873OISw/lDCCu2b+eewEAN5BLsv/OoL8XIPWzDSQdh4UiOlDYgfuoRevwbiYsfeKcUmq +RKYqN/U18XYk7FDOqyprzye1kJpZSIXee9AZ0ux/sthDKDewW7+FoYCNzbD/C23xRtCIlejwEVEB +lOtR9EN6W46XTbHrWJPORo8n4uxEDheo4J8XdlKxYRmxb8yQRbCinw7cbjVs9qvx6uAPIXMnVJ1G +RZTp+RhWW7NlX4YQSC7cgVkc4rB9M4I3z9NScna8wPjsQw7W+ApFeDAvwSNlKWsCB3aC4QYJ9Opb +v6JYLiTo0+ndRs44KYI4CJgbokGpcYXFyvS6LrqC02uGeXp66UehtQZ2wRgUBIMZ1hZzkQKLcda9 +HZ0xNazpN8YDZptOywO2xw9Jdkiai3OlzpKr8hNeEo/vIh9yRAQr/qrxykYfzD3LleLF+PUL6Uqb +O2urVGb6bPO8nJLhG4rghD/krfYwyBp4LUYSEJwM0e/1gLPqh69k/RdDJss9voDvFtYuF4KgwP1i +kWNmtgJsYdHDclcNdjZY04hg/uHm3jyHKb8UciI62hvpzkZLQVYgZH1z1aAfq5Ib9B+yhXThRpB5 +5tHwtZXA6QqFUh3C8Is7na7fzlNn5ApI4QWSWJF/IOD7lAHbhva0uyMkO9YHazHiH7JrD4d+fiCF +8b1RiV1xNkxNPbzifOsWhj8kp0VFTsO282OdEc0s/TmpB3ygU07BZJohPRx0as1puk7OhUA/QFKI +pyBSkPrzQ3ethVFWbn+XQv18Lvh9RqhL3u4+8ocszz4ElA4uiNSaT8LkANv+HFgPxc+GHlJ+dmcX +zRZCKyW7aKOZC5AjkrnemGQaGvd8VCZWR0hl5G5YW6SP/rz8kddjnprBaVobDAdRoqiY1bU+emdj +rFuZ0cXM2ufJIAyWaMXkdq4ZKaOP9/JUHgr/0lgOoo2mcBynS9FH0w8JW//IQKzEagkU4OBqLjW3 +/CZWYv9ZMKX06ritNgYzc0zvhiFeIgGoHjFCvlSKvqTVqI7hgGTPHAd1pFYpEjJFkBGS9ZIhkNZw +DDHlXNr5C9tH1+0ME72wae8tWyEfageVvUV1FCyo9nwPR0BxWAcPU8AE/DQY1ukrVenC7h14T+Hp +HemCvtUH6Y9mVF8mGxZ84Lq8rCB2lN/lD3xEsSuF5ypWJE/Ncp0DVEUIjhOgB900MlabV7UsYQ+b +hRaHUFPlxl7nvyW5SAjknN4iv06CIx8hAobbqgCC2P+ijoA5SQAB1AjuEAAAXlQMULHEZ/sCAAAA +AARZWg==