From 8da111017d15c6e091c171278b45f9720d043efc Mon Sep 17 00:00:00 2001 From: Tomas Baca Date: Tue, 3 Dec 2024 16:25:45 +0100 Subject: [PATCH] + portainer --- .../30-docker/60-airgapped-machines.md | 7 - .../30-docker/60-offline-machines.md | 7 + docs/10-prerequisities/32-portainer.md | 7 - .../32-portainer/01-starting.md | 126 ++++++ .../32-portainer/10-connecting-to.md | 13 + .../32-portainer/50-example-stacks.md | 371 ++++++++++++++++++ .../32-portainer/fig/portainer_login.png | Bin 0 -> 28068 bytes docs/10-prerequisities/32-portainer/index.md | 20 + 8 files changed, 537 insertions(+), 14 deletions(-) delete mode 100644 docs/10-prerequisities/30-docker/60-airgapped-machines.md create mode 100644 docs/10-prerequisities/30-docker/60-offline-machines.md delete mode 100644 docs/10-prerequisities/32-portainer.md create mode 100644 docs/10-prerequisities/32-portainer/01-starting.md create mode 100644 docs/10-prerequisities/32-portainer/10-connecting-to.md create mode 100644 docs/10-prerequisities/32-portainer/50-example-stacks.md create mode 100644 docs/10-prerequisities/32-portainer/fig/portainer_login.png create mode 100644 docs/10-prerequisities/32-portainer/index.md diff --git a/docs/10-prerequisities/30-docker/60-airgapped-machines.md b/docs/10-prerequisities/30-docker/60-airgapped-machines.md deleted file mode 100644 index f88ede09..00000000 --- a/docs/10-prerequisities/30-docker/60-airgapped-machines.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Airgapped machines -pagination_label: Working with airgapped machines -description: How to work with airgapped machines ---- - -# Airgapped machines with Docker diff --git a/docs/10-prerequisities/30-docker/60-offline-machines.md b/docs/10-prerequisities/30-docker/60-offline-machines.md new file mode 100644 index 00000000..29d87c19 --- /dev/null +++ b/docs/10-prerequisities/30-docker/60-offline-machines.md @@ -0,0 +1,7 @@ +--- +title: Offline machines +pagination_label: Working with offline machines +description: How to work with offline machines +--- + +# Offline machines with Docker diff --git a/docs/10-prerequisities/32-portainer.md b/docs/10-prerequisities/32-portainer.md deleted file mode 100644 index 1dee8bc5..00000000 --- a/docs/10-prerequisities/32-portainer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Portainer.io -pagination_label: Deploying Docker with Portainer.io -description: Deploying Docker with Portainer.io ---- - -# Portainer.io diff --git a/docs/10-prerequisities/32-portainer/01-starting.md b/docs/10-prerequisities/32-portainer/01-starting.md new file mode 100644 index 00000000..bdc6f80e --- /dev/null +++ b/docs/10-prerequisities/32-portainer/01-starting.md @@ -0,0 +1,126 @@ +--- +title: Starting Portainer +pagination_label: Starting Portainer +description: Starting Portainer +--- + +# Starting Portainer + +Portainer can be started using a simple compose session. +By default, the containers will respawn when the computer restarts. + +## Portainer Agent + +The Portainer Agent is responsible for communicating with the local docker daemon. + +
+Compose file + +```yaml +services: + + portainer_agent: + + image: portainer/agent:2.21.0 + + ports: + - 9001:9001 + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker/volumes:/var/lib/docker/volumes + - /:/host + + restart: always +``` + +
+ +## Portainer Server + +The Portainer Server is what creates the Web UI. +A single server can be connected to more than one **agent**. + +
+Compose file + +```yaml +volumes: + + portainer_data: + +services: + + portainer: + + image: portainer/portainer-ce:2.21.0 + + ports: + - 8000:8000 + - 9000:9000 + - 9443:9443 + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + + restart: always + + command: --http-enabled +``` + +
+ +## Both the Agent and the Server on a single machine + +In case of a single robot, we might run both on a single machine. +In that case, a single session for both will suffice. + +
+Compose file + +```yaml +volumes: + + portainer_data: + +services: + + portainer_agent: + + image: portainer/agent:2.21.2 + + network_mode: host + + ports: + - 9001:9001 + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker/volumes:/var/lib/docker/volumes + - /:/host + + restart: always + + portainer: + + image: portainer/portainer-ce:2.21.2 + + network_mode: host + + ports: + - 8000:8000 + - 9000:9000 + - 9443:9443 + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + + restart: always + + command: --http-enabled + +``` + +
diff --git a/docs/10-prerequisities/32-portainer/10-connecting-to.md b/docs/10-prerequisities/32-portainer/10-connecting-to.md new file mode 100644 index 00000000..11a3f62d --- /dev/null +++ b/docs/10-prerequisities/32-portainer/10-connecting-to.md @@ -0,0 +1,13 @@ +--- +title: Connecting to Portainer +pagination_label: Connecting to Portainer +description: Connecting to Portainer +--- + +# Connecting to portainer + +1. Open your web browser +2. Determine the hostname of the machine that run Portainer (e.g., `localhost`, or `uav1`) +3. Open the url [https://localhost:9443](https://localhost:9443) (substitude your hostname) + +![](./fig/portainer_login.png) diff --git a/docs/10-prerequisities/32-portainer/50-example-stacks.md b/docs/10-prerequisities/32-portainer/50-example-stacks.md new file mode 100644 index 00000000..e78747a5 --- /dev/null +++ b/docs/10-prerequisities/32-portainer/50-example-stacks.md @@ -0,0 +1,371 @@ +--- +title: Example stacks +pagination_label: Example Portainer stacks (compose sessions) +description: Example Portainer stacks (compose sessions) +--- + +# Example stacks + +Stacks are **docker compose sessions** within portainer. +As in vanilla docker, stacks are defined by a [compose file](/docs/prerequisities/docker/compose-sessions). +Moreover, a set of environment varibles is defined _by hand_ in Portainer, which can define how the session behave. + +## Example simulation session + +An example simulation session is located at [mrs_docker/tree/master/compose/1.5.0/portainer](https://github.com/ctu-mrs/mrs_docker/tree/master/compose/1.5.0/portainer). +Custom configs for the MRS UAV System are supposed to be packed into a transport docker image. +The subfolder `custom_configs` containes the example custom cofigs and scripts for build an image that is going to unload the configs during the runtime for the running containers. + +
+Compose file + +```yaml +volumes: + + shared_data: + + bag_files: + + logs: + +services: + + # will copy session-specific data shared between containers from the shared_data container to a shared volume + copy_shared_data: + image: ctumrs/gazebo_simulator:shared_data + volumes: + - shared_data:/tmp/docker/shared_data:consistent + tty: true + command: sh -c "rm -rvf /tmp/docker/shared_data/*; mkdir -pv /tmp/docker/shared_data; cp -rv /etc/docker/shared_data/* /tmp/docker/shared_data/" + + roscore: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + depends_on: + - copy_shared_data + env_file: + - ./stack.env + tty: true + command: roscore + + gazebo_simulator: + depends_on: + - roscore + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + # mount the folders below to enable passing GUI to the host + - /dev/dri:/dev/dri + - /tmp/.X11-unix:/tmp/.X11-unix + env_file: + - ./stack.env + environment: + DISPLAY: $DISPLAY + tty: true + command: bash -c "waitForRos && roslaunch mrs_uav_gazebo_simulation simulation.launch world_name:=grass_plane gui:=true" + + spawn: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c 'waitForGazebo; rosservice call /mrs_drone_spawner/spawn "1 --$$UAV_TYPE --enable-rangefinder"' + + hw_api: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForTime && roslaunch mrs_uav_px4_api api.launch" + + uav_core: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForHw && roslaunch mrs_uav_core core.launch platform_config:=`rospack find mrs_uav_gazebo_simulation`/config/mrs_uav_system/$$UAV_TYPE.yaml custom_config:=/etc/docker/shared_data/custom_config.yaml world_config:=/etc/docker/shared_data/world_config.yaml network_config:=/etc/docker/shared_data/network_config.yaml" + + automatic_start: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForHw && roslaunch mrs_uav_autostart automatic_start.launch custom_config:=/etc/docker/shared_data/automatic_start.yaml" + + # starts `rosbag record` + rosbag: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - bag_files:/etc/docker/bag_files:consistent + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForTime && /etc/docker/shared_data/record.sh" + + takeoff: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForControl && rosservice call /uav1/hw_api/arming 1 && sleep 1 && rosservice call /uav1/hw_api/offboard" + + rviz: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + # mount the folders below to enable passing GUI to the host + - /dev/dri:/dev/dri + env_file: + - ./stack.env + environment: + DISPLAY: $DISPLAY + tty: true + command: bash -c "waitForHw && roslaunch mrs_uav_core rviz.launch" + + rviz_interface: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - roscore + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + # mount the folders below to enable passing GUI to the host + - /dev/dri:/dev/dri + env_file: + - ./stack.env + environment: + DISPLAY: $DISPLAY + tty: true + command: bash -c "waitForHw && roslaunch mrs_rviz_plugins rviz_interface.launch" + + dogtail: + image: klaxalk/dogtail:latest + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - logs:/etc/logs:consistent + + # this container can be used to access a terminal with ROS inside the compose session + terminal: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + env_file: + - ./stack.env + entrypoint: ["/bin/bash", "-c"] + volumes: + - shared_data:/etc/docker/shared_data:consistent + - bag_files:/etc/docker/bag_files:consistent + - /dev/:/dev/ + - /tmp/.X11-unix:/tmp/.X11-unix + command: + - bash --rcfile /opt/ros/noetic/setup.bash + privileged: true + stdin_open: true + tty: true +``` + +
+ +
+Environment variables + +```bash +RUN_TYPE=simulation +UAV_NAME=uav1 +UAV_TYPE=x500 +ROS_MASTER_URI=http://localhost:11311 +MRS_UAV_SYSTEM_VERSION=1.5.0 +DISPLAY=:0 +``` + +
+ +## Example realworld UAV session + +An example realworld session is located at [mrs_docker/tree/master/compose/1.5.0/portainer](https://github.com/ctu-mrs/mrs_docker/tree/master/compose/1.5.0/portainer). +Custom configs for the MRS UAV System are supposed to be packed into a transport docker image. +The subfolder `custom_configs` containes the example custom cofigs and scripts for build an image that is going to unload the configs during the runtime for the running containers. + +
+Compose file + +```yaml +volumes: + + shared_data: + + bag_files: + + logs: + +services: + + # will copy session-specific data shared between containers from the shared_data container to a shared volume + copy_shared_data: + image: shared_data_gnss + volumes: + - shared_data:/tmp/docker/shared_data:consistent + tty: true + command: sh -c "rm -rvf /tmp/docker/shared_data/*; mkdir -pv /tmp/docker/shared_data; cp -rv /etc/docker/shared_data/* /tmp/docker/shared_data/" + + # starts roscore + # this is the first container in the ROS pipeline + roscore: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + depends_on: + - copy_shared_data + env_file: + - ./stack.env + tty: true + command: roscore + + # after roscore is started + # -> set a parameter that tells the system that simulation time is NOT used + # this container then stops + rostime: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + depends_on: + - roscore + env_file: + - ./stack.env + tty: true + command: bash -c "waitForRos && rosparam set use_sim_time false" + + # starts the HW API for connecting the MRS UAV System to PX4 + hw_api: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - rostime + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + - /dev/:/dev/ + privileged: true + env_file: + - ./stack.env + tty: true + command: bash -c "waitForTime && roslaunch mrs_uav_px4_api api.launch" + + # starts the MRS UAV System's core + uav_core: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - rostime + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForHw && roslaunch mrs_uav_core core.launch platform_config:=`rospack find mrs_uav_deployment`/config/mrs_uav_system/${UAV_TYPE}.yaml custom_config:=/etc/docker/shared_data/custom_config.yaml world_config:=/etc/docker/shared_data/world_local.yaml network_config:=/etc/docker/shared_data/network_config.yaml" + + # starts the node that handles automatic initialization of the system and takeoff + automatic_start: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - rostime + network_mode: host + volumes: + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForHw && roslaunch mrs_uav_autostart automatic_start.launch" + + # starts `rosbag record` + rosbag: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + depends_on: + - rostime + network_mode: host + volumes: + - bag_files:/etc/docker/bag_files:consistent + - shared_data:/etc/docker/shared_data:consistent + env_file: + - ./stack.env + tty: true + command: bash -c "waitForTime && /etc/docker/shared_data/record.sh" + + rosbridge: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + env_file: + - ./stack.env + tty: true + command: bash -c "waitForRos && roslaunch rosbridge_server rosbridge_websocket.launch" + + dogtail: + image: klaxalk/dogtail:latest + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - logs:/etc/logs:consistent + + # this container can be used to access a terminal with ROS inside the compose session + terminal: + image: ctumrs/mrs_uav_system:${MRS_UAV_SYSTEM_VERSION} + network_mode: host + depends_on: + - rostime + env_file: + - ./stack.env + entrypoint: ["/bin/bash", "-c"] + volumes: + - bag_files:/etc/docker/bag_files:consistent + - shared_data:/etc/docker/shared_data:consistent + - /dev/:/dev/ + command: + - bash --rcfile /opt/ros/noetic/setup.bash + privileged: true + stdin_open: true + tty: true +``` + +
+ +
+Environment variables + +```bash +RUN_TYPE=realworld +UAV_NAME=uav80 +UAV_TYPE=x500 +ROS_MASTER_URI=http://localhost:11311 +UAV_MASS=2.0 +MRS_UAV_SYSTEM_VERSION=1.5.0 +``` + +
diff --git a/docs/10-prerequisities/32-portainer/fig/portainer_login.png b/docs/10-prerequisities/32-portainer/fig/portainer_login.png new file mode 100644 index 0000000000000000000000000000000000000000..33c9d1586e5951e8e291f9b3b9773e84686d29a0 GIT binary patch literal 28068 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