# syntax=docker/dockerfile:1.7 # ------------------------------------------------------------------------------------- # Samba 4.22 Active Directory Domain Controller on Debian 13 (trixie) # # One `samba` process serves the whole DC role: # DNS 53 LDAP 389 / LDAPS 636 Global Catalog 3268 / 3269 # Kerberos 88 kpasswd 464 RPC epmapper 135 SMB 445 (SYSVOL/NETLOGON) # MS-SNTP 123 (Windows clients sync time from the DC after domain join) # # Build: docker build -t local/samba-ad-dc:4.22-debian13 -f image/Dockerfile . # ------------------------------------------------------------------------------------- FROM debian:trixie-slim # Pin every Samba-built package to the SAME version string (they carry exact-version # depends on each other, so pinning only `samba` produces unsatisfiable deps once the # archive carries two point releases). Empty => whatever trixie+security currently offer. ARG SAMBA_VERSION=2:4.22.11+dfsg-0+deb13u1 LABEL org.opencontainers.image.title="samba-ad-dc" \ org.opencontainers.image.description="Samba AD Domain Controller (Windows 11 join compatible) on Debian 13" \ org.opencontainers.image.source="https://github.com/local/samba-ad-dc" \ org.opencontainers.image.licenses="GPL-3.0-or-later" ENV DEBIAN_FRONTEND=noninteractive # Package postinsts must never try to start services during an image build. RUN printf '#!/bin/sh\nexit 101\n' > /usr/sbin/policy-rc.d && chmod 0755 /usr/sbin/policy-rc.d RUN set -eux; \ pin=""; \ if [ -n "${SAMBA_VERSION}" ]; then pin="=${SAMBA_VERSION}"; fi; \ apt-get update; \ apt-get install -y --no-install-recommends \ "samba${pin}" \ "samba-ad-dc${pin}" \ "samba-common${pin}" \ "samba-common-bin${pin}" \ "samba-dsdb-modules${pin}" \ "samba-ad-provision${pin}" \ "python3-samba${pin}" \ "winbind${pin}" \ python3-setproctitle \ krb5-user \ libsasl2-modules-gssapi-mit \ ldap-utils \ smbclient \ bind9-dnsutils \ python3-dnspython \ ca-certificates \ openssl \ iproute2 \ procps \ tzdata; \ rm -f /usr/sbin/policy-rc.d; \ rm -rf /var/lib/apt/lists/*; \ # The stock smb.conf/krb5.conf shipped by the packages must NOT exist: # the entrypoint uses their absence to detect a virgin data volume, and named # volumes would otherwise be seeded with the stock (non-AD) config. rm -f /etc/samba/smb.conf /etc/krb5.conf; \ mkdir -p /etc/samba /var/backups/ad-dc /run/ad-secrets; \ # Leave the AD state dir EMPTY. Docker seeds named volumes from the image's content, # and `samba-tool domain backup restore` refuses a non-empty target dir. Provisioning # creates these directories itself. rm -rf /var/lib/samba; \ mkdir -p /var/lib/samba; \ # sanity: this image is useless without the AD DC bits test -x /usr/sbin/samba; \ /usr/bin/samba-tool --help >/dev/null; \ # the AD schema lives in a separate Debian package (samba-ad-provision) - fail the # build here rather than at first-run provisioning ls /usr/share/samba/setup/ad-schema/AD_DS_Attributes_Windows_Server_v1903.ldf >/dev/null; \ # ldap-client GSSAPI and smbclient are used by the verification scripts ls /usr/lib/*/sasl2/libgssapiv2.so >/dev/null; \ command -v smbclient >/dev/null; \ command -v kvno >/dev/null; \ samba -V COPY image/ad-entrypoint.sh /usr/local/bin/ad-entrypoint COPY image/ad-healthcheck.sh /usr/local/bin/ad-healthcheck COPY image/ad-dnsupdate.sh /usr/local/bin/ad-dnsupdate RUN chmod 0755 /usr/local/bin/ad-entrypoint /usr/local/bin/ad-healthcheck /usr/local/bin/ad-dnsupdate # Documentation only (real ports come from the network mode you choose). EXPOSE 53/tcp 53/udp 88/tcp 88/udp 123/udp 135/tcp 137/udp 138/udp 139/tcp \ 389/tcp 445/tcp 464/tcp 464/udp 636/tcp 3268/tcp 3269/tcp # start_period is generous: first-run provisioning takes ~30-90s. HEALTHCHECK --interval=30s --timeout=20s --start-period=120s --retries=4 \ CMD ["/usr/local/bin/ad-healthcheck"] ENTRYPOINT ["/usr/local/bin/ad-entrypoint"]