prind icon indicating copy to clipboard operation
prind copied to clipboard

Setting up project in portainer

Open HitLuca opened this issue 3 years ago • 4 comments

I am currently using the klipper-web-control-docker project for controlling my printer from my nas, but I discovered this project and I am interested in trying it out.

Is there documentation on how to set it up in Portainer? My biggest issue is having to populate the docker-compose.override.yaml, which I don't think it's possible in Portainer

HitLuca avatar Oct 15 '22 16:10 HitLuca

There is currently no documentation on how to set this up in portainer, as I am unfamiliar with it.
From a short glance at the portainer docs, there is no way to provide an override file for compose, I'm also unsure about if portainer actually uses compose under the hood or is just able to interpret the compose spec.

You could try to add your personal settings directly to the main docker-compose file and then uploading it to portainer.
The issue I see here is, that the config directory is used as a docker volume and I'm not sure if you can upload the directory structure with the prefilled config files into portainer.

You may want to create a simple docker-compose file that only consists of the services you'd like to run and also holds the config files in an actual docker volume instead of a bind mounted directory from within this repository.

I'd be happy to add a portainer guide if you get it to work.

-Markus

mkuf avatar Oct 17 '22 13:10 mkuf

@HitLuca Hello I'm by no means an expert on docker or Portainer.

With some help from a friend and a lot of reading online I'm able to run prind from Portainer (Community Edition 2.15.1) with the following configuration.

I have commend out the stuff i don't need and i can add what i want for example ustreamer inside the main config. Obviously you have to change folder paths etc to your need's and don't forget to change the "devices:" port under "klipper:".

I hope it helps.

image

## Common Templates NEW v1.1.1.txt

gminadak avatar Oct 20 '22 20:10 gminadak

Thanks @gminadak,

your config seems to be in line with my suggestion.

  • It removes the profile functionality and sets up services in a static way
  • it is using /data/prind as a directory for all volume mounts that are usually created as docker volumes

I have two questions about this setup:

  1. The comment you added at the Top of the file suggests to set permissions on that directory as traefik would then not find the moonraker container. Could you elaborate on which permissions should be set?
    This sounds like what the init Service is doing once before moonraker/klipper start. Traefik probably has no issues in finding the moonraker container, but the container is stuck in a restart loop as the permissions on the files are set wrong.

  2. Is there a reason to not use docker volumes for gcode, run, log and moonraker-db and instead mount a local directory? I'd assume it would be enough to change the location for the config directory and keep using docker volumes for everything else.

-Markus

mkuf avatar Oct 23 '22 18:10 mkuf

Based on the file provided by @gminadak and some of my own assumptions I created a file that might be used with portainer.
It currently lives in a separate branch but I'd like to merge it into main if I receive positive Feedback.

I'd be happy if one of you could give it a try and report back. Please pay attention to the setup notes at the Top of the file. https://github.com/mkuf/prind/blob/custom-templates/custom/docker-compose.custom.portainer.yaml

-Markus

mkuf avatar Oct 23 '22 20:10 mkuf

Testing this approach now, as first feedback I can say that the yaml provided by @mkuf has a

profiles:
  - fluidd

section that should be removed, or the fluidd container wouldn't launch. I had to remove the init container as I couldn't get it to work, but I seem to be able to use the printer without issues.

I am quite in a hurry these days so I cannot finish testing everything, but will add updates as I make progress

HitLuca avatar Oct 25 '22 09:10 HitLuca

@mkuf Sorry for the late reply. Having the volumes gcode, log and moonraker-db (run is on the default location) on different locations is my preference as portainer will place it under /var/lib/docker/volumes/ image

And because you can delete the volumes directly from Portainer you can very easily lose all you gcode files, and the moonraker-db (yeap I did that once!) also you need to sudo su every time you need to access this folder.

Make sure your printer is connected and powered on before you start the "stack" or Portainer will throw an error (the first time only then it will work fine as long as the stack runs) image

and you will have to remove the containers by hand for the stack to start again image

Don't ever select this!!! If you use non-persistent volumes it will erase all data as I say before image

I have already test your config as you can see and work's fine.

gminadak avatar Oct 25 '22 14:10 gminadak

@mkuf Sorry my bad you need to remove lines 84, 85 from your config for fluid to start

gminadak avatar Oct 25 '22 14:10 gminadak

Thanks for your Feedback @HitLuca and @gminadak
The profile has been removed from the fluidd service in https://github.com/mkuf/prind/commit/4fce13be42703abf74cecb66c6d34de0e4daeb42

Did the init conainer work for you @gminadak?

-Markus

mkuf avatar Oct 25 '22 15:10 mkuf

@mkuf

  1. The comment you added at the Top of the file suggests to set permissions on that directory as traefik would then not find the moonraker container. Could you elaborate on which permissions should be set? This sounds like what the init Service is doing once before moonraker/klipper start. Traefik probably has no issues in finding the moonraker container, but the container is stuck in a restart loop as the permissions on the files are set wrong.

As I test the configuration and starting to remember thinks....the second reason is that Portainer will make all folders on the persistent volume as root as you mentioned image Strange think is it's the same as with non persistent volumes and works fine image and Traefik will start to throw errors. image As soon as I change the permissions to user everything work's fine image

Did the init conainer work for you @gminadak?

From what I can see it changed the user:group on /config fine image but I had to create/copy the folder config by hand for the container to start image

I had to restore my old VM-docker-portainer backup to test all this as I have now move the setup to VM without docker-portainer just plain KIAUH installation!

gminadak avatar Oct 25 '22 15:10 gminadak

Thanks. Based on your feedback I'll merge the custom templates into main for everyone to use.

mkuf avatar Oct 27 '22 15:10 mkuf

Implemented with https://github.com/mkuf/prind/commit/ff4ca0222645677ef88b765666e7a54d67d53fc1.
Feel free to create pull requests if you encounter issues with the portainer template.

mkuf avatar Oct 27 '22 15:10 mkuf

@mkuf I recently assembled a new 3d printer, and had to do a multi-printer setup in portainer. It may be helpful to know what a working code would look like, I took out traefik and basically duplicated the examples in order to get it to work

I have both mainsail and fluidd running, and each printer has been connected using the my_hostname:8013 and my_hostname:8014. I don't have webcams setup yet so I took out the streamer service. Should be easy enough to add back tho.


services:
  eryopne-thinker-se-klipper:
    image: mkuf/klipper:latest
    restart: unless-stopped
    logging:
      driver: none
    depends_on:
      eryopne-thinker-se-init:
        condition: service_completed_successfully
    command: -I printer_data/run/klipper.tty -a printer_data/run/klipper.sock printer_data/config/printer.cfg -l printer_data/logs/klippy.log
    devices:
      - ${ERYONE_THINKER_SE_SERIAL_INTERFACE}:${ERYONE_THINKER_SE_SERIAL_INTERFACE}
    volumes:
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/config:/opt/printer_data/config
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/run:/opt/printer_data/run
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/gcode:/opt/printer_data/gcodes
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/log:/opt/printer_data/logs
    labels:
      org.prind.service: klipper
      org.prind.printer: eryopne-thinker-se
      
  eryopne-thinker-se-moonraker:
    image: mkuf/moonraker:latest
    restart: unless-stopped
    pid: host
    privileged: true
    #logging:
    #  driver: none
    depends_on:
      eryopne-thinker-se-init:
        condition: service_completed_successfully
      eryopne-thinker-se-klipper:
        condition: service_started
    ports:
      - 8013:7125
    volumes:
      - /dev/null:/opt/klipper/config/null
      - /dev/null:/opt/klipper/docs/null
      - /run/dbus:/run/dbus
      - /run/systemd:/run/systemd
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/run:/opt/printer_data/run
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/gcode:/opt/printer_data/gcodes
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/log:/opt/printer_data/logs
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/moonraker-db:/opt/printer_data/database
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}/config:/opt/printer_data/config
    labels:
      org.prind.service: moonraker
      org.prind.printer: eryopne-thinker-se

  eryopne-thinker-se-init:
    image: busybox:latest
    command: chown -R 1000:1000 /prind/config
    volumes:
      - ${ERYONE_THINKER_SE_CONFIG_FOLDER}:/prind
    labels:
      org.prind.service: init
      org.prind.printer: eryopne-thinker-se
      
  voron-0-klipper:
    image: mkuf/klipper:latest
    restart: unless-stopped
    logging:
      driver: none
    depends_on:
      voron-0-init:
        condition: service_completed_successfully
    command: -I printer_data/run/klipper.tty -a printer_data/run/klipper.sock printer_data/config/printer.cfg -l printer_data/logs/klippy.log
    devices:
      - ${VORON_0_SERIAL_INTERFACE}:${VORON_0_SERIAL_INTERFACE}
    volumes:
      - ${VORON_0_CONFIG_FOLDER}/config:/opt/printer_data/config
      - ${VORON_0_CONFIG_FOLDER}/run:/opt/printer_data/run
      - ${VORON_0_CONFIG_FOLDER}/gcode:/opt/printer_data/gcodes
      - ${VORON_0_CONFIG_FOLDER}/log:/opt/printer_data/logs
    labels:
      org.prind.service: klipper
      org.prind.printer: voron-0
      
  voron-0-moonraker:
    image: mkuf/moonraker:latest
    restart: unless-stopped
    pid: host
    privileged: true
    #logging:
    #  driver: none
    depends_on:
      voron-0-init:
        condition: service_completed_successfully
      voron-0-klipper:
        condition: service_started
    ports:
      - 8014:7125
    volumes:
      - /dev/null:/opt/klipper/config/null
      - /dev/null:/opt/klipper/docs/null
      - /run/dbus:/run/dbus
      - /run/systemd:/run/systemd
      - ${VORON_0_CONFIG_FOLDER}/run:/opt/printer_data/run
      - ${VORON_0_CONFIG_FOLDER}/gcode:/opt/printer_data/gcodes
      - ${VORON_0_CONFIG_FOLDER}/log:/opt/printer_data/logs
      - ${VORON_0_CONFIG_FOLDER}/moonraker-db:/opt/printer_data/database
      - ${VORON_0_CONFIG_FOLDER}/config:/opt/printer_data/config
    labels:
      org.prind.service: moonraker
      org.prind.printer: voron-0

  voron-0-init:
    image: busybox:latest
    command: chown -R 1000:1000 /prind/config
    volumes:
      - ${VORON_0_CONFIG_FOLDER}:/prind
    labels:
      org.prind.service: init
      org.prind.printer: voron-0
      
  mainsail:
    image: ghcr.io/mainsail-crew/mainsail:edge
    restart: unless-stopped
    ports:
      - 8011:80
    volumes:
      - ${MAINSAIL_CONFIG_FOLDER}/mainsail-config.json:/usr/share/nginx/html/config.json
    labels:
      org.prind.service: mainsail
      
  fluidd:
    image: cadriel/fluidd:latest
    restart: unless-stopped
    ports:
      - 8012:80
    labels:
      org.prind.service: fluidd

The setup uses portainer env vars to work, here is what I used:

MAINSAIL_CONFIG_FOLDER=/.../prind
ERYONE_THINKER_SE_CONFIG_FOLDER=/...prind/eryone_thinker_se
ERYONE_THINKER_SE_SERIAL_INTERFACE=/dev/serial/by-id/...

VORON_0_CONFIG_FOLDER=/.../prind/voron_0
VORON_0_SERIAL_INTERFACE=/dev/serial/by-id/...
RPI_PICO_SERIAL_INTERFACE=/dev/serial/by-id/...

the RPI_PICO_SERIAL_INTERFACE is used whenever I want to do input shaping, I would just have to add a new device mapping to the relevant klipper service and restart it.

As you can see I use separate folders for each printer, in my opinion this is nicer since each printer is completely separate from the other.

The mainsail-config.json file just contains


{
  "instancesDB": "json",
  "instances": [
    { "hostname": "my-hostname", "port": 8013 },
    { "hostname": "my-hostname", "port": 8014 }
  ]
}



to have the printer already set up in the web interface

To avoid issues with moonraker blocking mainsail/fluidd, and since it's a local-only setup, I removed authorization and allowed all local ips to connect to the services like this (moonraker.conf)

[machine]
provider: systemd_cli
validate_service: False

[authorization]
force_logins: False

trusted_clients:
  10.0.0.0/8
  127.0.0.0/8
  169.254.0.0/16
  172.16.0.0/12
  192.168.0.0/16
  FE80::/10
  ::1/128

cors_domains:
  *

[octoprint_compat]

[history]

The single issue I'm having is that fluidd complains that I don't have a CANCEL_PRINT macro, even though I have it on my configs (using the https://github.com/jschuh/klipper-macros project which has been working just fine since I started using it)

The label org.prind.printer has been used in order to restart klipper whenever a printer is power cycled, following my solution in https://github.com/mkuf/prind/issues/51, and just changing how you get the correct klipper container in the script you posted (klipper_container=$(docker ps -aqf "label=org.prind.printer=the_interested_printer")). I have a restart_printer.sh script for each printer in their prind subfolder,and a udev rule which checks for both mainboards for power cycling. When this happens it just calls the correct script

HitLuca avatar Jan 12 '23 10:01 HitLuca

May as well also add my configuration for klipperscreen:

In portainer

  klipperscreen:
    image: mkuf/klipperscreen:latest
    restart: unless-stopped
    network_mode: host
    environment:
      DISPLAY: ${KLIPPERSCREEN_IP}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /tmp/.X11-unix:/tmp/.X11-unix
      - ${CONFIG_FOLDER}/klipperscreen.conf:/opt/cfg/klipperscreen.conf
    labels:
      org.prind.service: klipperscreen

the env var KLIPPERSCREEN_IP is the ip of my phone as shown in the xserver app, like 192.168.1.2:0

I moved the klipperscreen.conf file in the root of my prind config folder, and the contents for two printers are

[printer eryone-thinker-se]
moonraker_port: 8013

[printer voron-0]
moonraker_port: 8014
#~# --- Do not edit below this line. This section is auto generated --- #~#
#~#
#~# [main]
#~# use_dpms = False
#~#

HitLuca avatar Jan 12 '23 10:01 HitLuca