Open Zen3515 opened 9 months ago
Essentially, you need to create three services.
avahi-daemon in /etc/services.d/avahi-daemon/run
#!/usr/bin/execlineb -P
/usr/sbin/avahi-daemon -s
cups in /etc/services.d/cups/run
#!/usr/bin/execlineb -P
/usr/sbin/cupsd -l
cups-browsed in /etc/services.d/cups-browsed/run
#!/usr/bin/execlineb -P
/usr/sbin/cups-browsed
And modify your Dockerfile accordingly.
FROM debian:stable-slim
# ENV variables
ENV DEBIAN_FRONTEND noninteractive
ENV TZ "America/New_York"
ENV CUPSADMIN admin
ENV CUPSPASSWORD password
LABEL org.opencontainers.image.source="https://github.com/anujdatar/cups-docker"
LABEL org.opencontainers.image.description="CUPS Printer Server"
LABEL org.opencontainers.image.author="Anuj Datar <anuj.datar@gmail.com>"
LABEL org.opencontainers.image.url="https://github.com/anujdatar/cups-docker/blob/main/README.md"
LABEL org.opencontainers.image.licenses=MIT
# Install s6-overlay
ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64.tar.gz /tmp/
# Install dependencies
RUN apt-get update -qq && apt-get upgrade -qqy \
&& apt-get install -qqy \
apt-utils \
usbutils \
cups \
cups-filters \
printer-driver-all \
printer-driver-cups-pdf \
printer-driver-foo2zjs \
foomatic-db-compressed-ppds \
openprinting-ppds \
hpijs-ppds \
hp-ppd \
hplip \
avahi-daemon \
&& tar xzf /tmp/s6-overlay-amd64.tar.gz -C / \
&& rm /tmp/s6-overlay-amd64.tar.gz \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 631
EXPOSE 5353/udp
# Baked-in config file changes
RUN sed -i 's/Listen localhost:631/Listen 0.0.0.0:631/' /etc/cups/cupsd.conf && \
sed -i 's/Browsing Off/Browsing On/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/>/<Location \/>\n Allow All/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/admin>/<Location \/admin>\n Allow All\n Require user @SYSTEM/' /etc/cups/cupsd.conf && \
sed -i 's/<Location \/admin\/conf>/<Location \/admin\/conf>\n Allow All/' /etc/cups/cupsd.conf && \
echo "ServerAlias *" >> /etc/cups/cupsd.conf && \
echo "DefaultEncryption Never" >> /etc/cups/cupsd.conf
# back up cups configs in case used does not add their own
RUN cp -rp /etc/cups /etc/cups-bak
VOLUME [ "/etc/cups" ]
# Add s6 service definitions
COPY ./services /etc/services.d
# Command to start s6-init
CMD ["/init"]
Something along these lines
aah, okay thanks.. I do not have a lot of experience with s6, or managing multiple services inside containers. Thanks for the examples. I honestly did not get a lot of time to experiment over the holidays. I literally only got a couple of hours to work on it, I know it doesn't work yet. I'll hopefully get to work on it again in a few weeks. Work's too busy at the moment.
Anuj
I could help you create this PR, but I have to think about how to incorporate the existing entrypoint script for adding user based on the env variable first.
I've created a PR for this, the only thing left to think about is how to build s6-overlay supporting multiple architecture.
I think you could add a script file which will be executed as one of the Dockerfile steps.
Something like this.
if [[ "${TARGETARCH}" == "amd64" ]]; then
S6_OVERLAY_ARCH="x86_64"
elif [[ "${TARGETARCH}" == "arm64" ]]; then
S6_OVERLAY_ARCH="aarch64"
fi
wget -qO- "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_OVERLAY_ARCH}.tar.xz" |
tar -C / -Jxpf -
But I'm not sure how we could know the TARGETARCH
via github action, based on the quick search, it should be something like this.
...
- name: Build and push images
uses: docker/build-push-action@v4
build-args: |
TARGETARCH=${{ matrix.arch }}
...
I found it mentioned here and here, TARGETARCH will be passed automatically with BuildKit.
Which architecture to use depending on your TARGETARCH
The
${arch}
part in thes6-overlay-${arch}.tar.xz
tarball uses the naming conventions of gcc, which are not the ones that Docker uses. (Everyone does something different in this field depending on their needs, and no solution is better than any other, but the Docker one is worse than others because its naming is inconsistent. The gcc convention is better for us because it simplifies our builds greatly and makes them more maintainable.)The following table should help you find the right tarball for you if you're using the TARGETARCH value provided by Docker:
${TARGETARCH} | ${arch} | Notes |
---|---|---|
amd64 | x86_64 | |
arm64 | aarch64 | |
arm/v7 | arm | armv7 with soft-float |
arm/v6 | armhf | Raspberry Pi 1 |
386 | i686 | i486 for very old hw |
riscv64 | riscv64 | |
s390x | s390x |
I've included multiple architecture support in the PR, it should be ready now.
Thanks for all the work. I'll test it out over the weekend and merge the request. Unfortunately I will not be able to get to this till Friday.
That's ok, let me know if any changes are required.
Hi @Zen3515 and @anujdatar thanks for all your work. Was this ever merged? Is there a fork where autodiscovery is working?
I saw your attempt to enable auto-discovery in this commit added avahi-daemon, and exposed port 5353/udp for multicast dns
While that's the correct direction, the normal linux systemd work in a little more complex way.
Specifically, compare to a normal working service, you also need to start process
avahi-daemon.service
andcups-browsed.service
You can look here
/usr/lib/systemd/system/cups-browsed.service
/etc/systemd/system/printer.target.wants/cups.service
/usr/lib/systemd/system/avahi-daemon.service
As you can see, it's quite complex to start all the services using your entrypoint.
In order to accomplish that you could take a look at
supervisord
andtini
or my prefered methods6-overlay
.With
s6-overlay
, you could create many services. Take a look at an example below (generated by ChatGPT)The s6-overlay is a powerful init system designed for use with Docker containers, allowing you to manage multiple processes within a single container. Here's a basic guide on how to use s6-overlay in a Dockerfile to start multiple processes:
Create a Dockerfile:
Create a new Dockerfile for your application. Here's a basic example:
In this example, replace
your-base-image
with the base image you want to use, and./app
with the path to your application files.Create a services directory:
Create a directory called
services
in the same directory as your Dockerfile. Inside this directory, you will define service scripts for each process you want to run.For example, if you want to run two processes, create files like
services/app1/run
andservices/app2/run
. The contents of these files might look like:These scripts will be executed by s6 when the container starts.
Build your Docker image:
Run the following command to build your Docker image:
Run your Docker container:
Now, you can run your Docker container:
The s6-overlay will manage the specified processes, and you can scale this approach to include more services as needed. The key is to create service scripts in the
services
directory, and s6 will take care of starting and managing those services within the Docker container.