@@ -787,11 +787,11 @@ <h1>Docker Executables: No More Install Guides</h1>
787787< h3 id ="why_we_built_this "> Why We Built This< a class ="headerlink " href ="#why_we_built_this " title ="Permanent link "> #</ a > </ h3 >
788788< ul >
789789< li > < strong > Installation struggles:</ strong > Some tools require long setup guides, heavy
790- dependencies, or fragile environment configs.</ li >
790+ dependencies, or fragile environment configs.</ li >
791791< li > < strong > Inconsistent environments:</ strong > A tool might behave differently across macOS,
792- Linux, and CI pipelines.</ li >
792+ Linux, and CI pipelines.</ li >
793793< li > < strong > Recurring time sink:</ strong > Installing and configuring utilities often leads to
794- wasted time debugging setups before real work can begin.</ li >
794+ wasted time debugging setups before real work can begin.</ li >
795795</ ul >
796796< h3 id ="how_it_works "> How It Works< a class ="headerlink " href ="#how_it_works " title ="Permanent link "> #</ a > </ h3 >
797797< p > When a developer runs a command, our wrapper script:</ p >
@@ -807,52 +807,58 @@ <h3 id="how_it_works">How It Works<a class="headerlink" href="#how_it_works" tit
807807< h3 id ="example_document_conversion_via_a_dockerized_executable "> Example: Document Conversion Via a Dockerized Executable< a class ="headerlink " href ="#example_document_conversion_via_a_dockerized_executable " title ="Permanent link "> #</ a > </ h3 >
808808< p > < strong > Goal:</ strong > Convert a < code > .docx</ code > file to Markdown without installing the converter
809809locally.</ p >
810- < div class =" highlight " > < pre > < span > </ span > < code > python < span class ="w " > </ span > dev_scripts_helpers/documentation/convert_docx_to_markdown.py< span class =" w " > </ span > < span class =" se " > \ </ span >
811- < span class =" w " > </ span > -i < span class =" w " > </ span > docs/weekly_update.docx< span class =" w " > </ span > < span class =" se " > \ </ span >
812- < span class =" w " > </ span > -o < span class =" w " > </ span > docs/weekly_update.md
813- </ code > </ pre > </ div >
810+ < pre > < code class ="language-bash " > python dev_scripts_helpers/documentation/convert_docx_to_markdown.py \
811+ -i docs/weekly_update.docx \
812+ -o docs/weekly_update.md
813+ </ code > </ pre >
814814< p > < strong > What happens under the hood (aligned with our flow):</ strong > </ p >
815815< ul >
816816< li > The Wrapper Ensures the Converter’S Docker Image Is Available (Pull/Build
817- if needed). </ li >
817+ if needed). </ li >
818818< li > The Repository (And the < code > docs/</ code > Files) Is Mounted Into the Container
819- (e.g., at < code > /src</ code > ).</ li >
819+ (e.g., at < code > /src</ code > ).</ li >
820820< li > Paths Are Mapped Automatically (E.G., < code > docs/weekly_update.docx</ code > →
821- < code > /src/docs/weekly_update.docx</ code > ).</ li >
821+ < code > /src/docs/weekly_update.docx</ code > ).</ li >
822822< li > The Tool Runs Inside the Container; the Generated < code > docs/weekly_update.md</ code >
823- is written back to your workspace.</ li >
823+ is written back to your workspace.</ li >
824824</ ul >
825825< p > < strong > Outcome:</ strong > Same result as a local install, but with no host setup, consistent
826826behavior across macOS/Linux/CI, and version-controlled tooling.</ p >
827827< h3 id ="other_examples_weve_dockerized "> Other Examples We’Ve Dockerized< a class ="headerlink " href ="#other_examples_weve_dockerized " title ="Permanent link "> #</ a > </ h3 >
828828< ol >
829829< li >
830830< p > < strong > Formatting Docs/Code</ strong > </ p >
831- < pre > < code > - Script: `dev_scripts_helpers/documentation/dockerized_prettier.py`
832- - Use: Apply consistent formatting across Markdown and source files.
833- </ code > </ pre >
831+ < ul >
832+ < li > < strong > Script:</ strong > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/documentation/dockerized_prettier.py "> dockerized_prettier.py</ a > </ li >
833+ < li > Use: Apply consistent formatting across Markdown and source files.</ li >
834+ </ ul >
834835</ li >
835836< li >
836837< p > < strong > Diagram Rendering (Mermaid / Graphviz / Tikz)</ strong > </ p >
837- < pre > < code > - Scripts:
838- - `dev_scripts_helpers/documentation/dockerized_mermaid.py`
839- - `dev_scripts_helpers/documentation/dockerized_graphviz.py`
840- - `dev_scripts_helpers/documentation/dockerized_tikz_to_bitmap.py`
841- - Use: Render architecture/flow diagrams and convert vector sources to
842- bitmaps inside containers (no local installs).
843- </ code > </ pre >
838+ < ul >
839+ < li > Scripts: < ul >
840+ < li > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/documentation/dockerized_mermaid.py "> dockerized_mermaid.py</ a > </ li >
841+ < li > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/documentation/dockerized_graphviz.py "> dockerized_graphviz.py</ a > </ li >
842+ < li > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/documentation/dockerized_tikz_to_bitmap.py "> dockerized_tikz_to_bitmap.py</ a > </ li >
843+ </ ul >
844+ </ li >
845+ < li > Use: Render architecture/flow diagrams and convert vector sources to
846+ bitmaps inside containers (no local installs).</ li >
847+ </ ul >
844848</ li >
845849< li >
846850< p > < strong > Latex PDF Builds</ strong > </ p >
847- < pre > < code > - Script: `dev_scripts_helpers/documentation/dockerized_latex.py`
848- - Use: Build PDFs reproducibly without installing LaTeX on the host/dev container.
849- </ code > </ pre >
851+ < ul >
852+ < li > < strong > Script:</ strong > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/documentation/dockerized_latex.py "> dockerized_latex.py</ a > </ li >
853+ < li > Use: Build PDFs reproducibly without installing LaTeX on the host/dev container.</ li >
854+ </ ul >
850855</ li >
851856< li >
852857< p > < strong > Llm-Powered Markdown Transforms</ strong > </ p >
853- < pre > < code > - Script: `dev_scripts_helpers/llms/llm_transform.py`
854- - Use: Structured content rewrites (e.g., polishing notes to Markdown).
855- </ code > </ pre >
858+ < ul >
859+ < li > < strong > Script:</ strong > < a href ="https://github.com/causify-ai/helpers/blob/master/dev_scripts_helpers/llms/llm_transform.py "> llm_transform.py</ a > </ li >
860+ < li > Use: Structured content rewrites (e.g., polishing notes to Markdown).</ li >
861+ </ ul >
856862</ li >
857863</ ol >
858864< h3 id ="technical_guide_building_a_dockerized_executable "> Technical Guide: Building a Dockerized Executable< a class ="headerlink " href ="#technical_guide_building_a_dockerized_executable " title ="Permanent link "> #</ a > </ h3 >
@@ -887,22 +893,22 @@ <h4 id="high-level_steps">High-Level Steps<a class="headerlink" href="#high-leve
887893</ li >
888894</ ul >
889895< h4 id ="minimal_image_illustrative "> Minimal Image (Illustrative)< a class ="headerlink " href ="#minimal_image_illustrative " title ="Permanent link "> #</ a > </ h4 >
890- < div class =" highlight " > < pre > < span > </ span > < code > < span class ="k "> FROM</ span > < span class =" w " > </ span > < span class =" s " > debian:stable-slim</ span >
891- < span class =" c " > # Install Your Toolchain and Runtime Here</ span >
892- < span class =" c " > # RUN Apt-Get Update \</ span >
893- < span class =" c " > # && Apt-Get Install -Y <Your-Tool> <Dependencies> \</ span >
894- < span class =" c " > # && Rm -Rf /Var/Lib/Apt/Lists/*</ span >
896+ < pre > < code class ="language-dockerfile "> FROM debian:stable-slim
897+ # Install Your Toolchain and Runtime Here
898+ # RUN Apt-Get Update \
899+ # && Apt-Get Install -Y <Your-Tool> <Dependencies> \
900+ # && Rm -Rf /Var/Lib/Apt/Lists/*
895901
896- < span class =" c " > # Create a Non-Root User (Recommended)</ span >
897- < span class =" k " > RUN</ span > < span class =" w " > </ span > useradd< span class =" w " > </ span > -ms< span class =" w " > </ span > / bin/bash< span class =" w " > </ span > appuser
898- < span class =" k " > USER</ span > < span class =" w " > </ span > < span class =" s " > appuser</ span >
902+ # Create a Non-Root User (Recommended)
903+ RUN useradd -ms / bin/bash appuser
904+ USER appuser
899905
900- < span class =" c " > # Work Inside the Mounted Repository Path</ span >
901- < span class =" k " > WORKDIR</ span > < span class =" w " > </ span > < span class =" s " > / src</ span >
906+ # Work Inside the Mounted Repository Path
907+ WORKDIR / src
902908
903- < span class =" c " > # Use a Simple Shell Entrypoint; the Wrapper Supplies the Command</ span >
904- < span class =" k " > ENTRYPOINT</ span > < span class =" w " > </ span > < span class =" p " > [ </ span > < span class =" s2 " > "/bin/sh"</ span > < span class =" p " > , </ span > < span class =" w " > </ span > < span class =" s2 " > "-lc"</ span > < span class =" p " > ] </ span >
905- </ code > </ pre > </ div >
909+ # Use a Simple Shell Entrypoint; the Wrapper Supplies the Command
910+ ENTRYPOINT [ "/bin/sh", "-lc"]
911+ </ code > </ pre >
906912< h4 id ="wrapper_cli_responsibilities_summary "> Wrapper CLI Responsibilities (Summary)< a class ="headerlink " href ="#wrapper_cli_responsibilities_summary " title ="Permanent link "> #</ a > </ h4 >
907913< ul >
908914< li > Discover the < strong > Repo Root</ strong > .</ li >
@@ -918,82 +924,54 @@ <h4 id="why_discover_the_repo_root_matters">Why "discover the repo root" Matters
918924container. We use the < strong > repository root</ strong > as that anchor:</ p >
919925< ul >
920926< li > < strong > Consistent Path Mapping:</ strong > Inputs Like < code > docs/notes.md</ code > Are Resolved
921- relative to the repo root and then rewritten to the container path (e.g.,
922- < code > /src/docs/notes.md</ code > ). This avoids "file not found" errors from
923- absolute/host-specific paths.</ li >
927+ relative to the repo root and then rewritten to the container path (e.g.,
928+ < code > /src/docs/notes.md</ code > ). This avoids "file not found" errors from
929+ absolute/host-specific paths.</ li >
924930< li > < strong > Works From Any Subdirectory:</ strong > Developers Often Run Commands From
925- < code > docs/</ code > or < code > scripts/</ code > . Resolving paths against the repo root means the same
926- command works no matter where it’s launched.</ li >
931+ < code > docs/</ code > or < code > scripts/</ code > . Resolving paths against the repo root means the same
932+ command works no matter where it’s launched.</ li >
927933< li > < strong > Children Vs. Sibling Containers:</ strong > with Sibling Containers (Dev
928- container → host Docker → tool container), the mount must reference a
929- < strong > host-visible path</ strong > . Using the repo root ensures the right directory is
930- mounted across both patterns.</ li >
934+ container → host Docker → tool container), the mount must reference a
935+ < strong > host-visible path</ strong > . Using the repo root ensures the right directory is
936+ mounted across both patterns.</ li >
931937< li > < strong > Minimal, Predictable Mount:</ strong > Mounting Only the Repo Root Keeps the
932- environment lean and avoids exposing unrelated host directories.</ li >
938+ environment lean and avoids exposing unrelated host directories.</ li >
933939< li > < strong > CI Parity:</ strong > CI Checks Out the Repo Into Different Paths. A
934- repo-root–based mount keeps commands stable across laptops, dev containers,
935- and CI runners.</ li >
940+ repo-root–based mount keeps commands stable across laptops, dev containers,
941+ and CI runners.</ li >
936942</ ul >
937943< h4 id ="illustrative_container_invocation "> Illustrative Container Invocation< a class ="headerlink " href ="#illustrative_container_invocation " title ="Permanent link "> #</ a > </ h4 >
938- < div class =" highlight " > < pre > < span > </ span > < code > docker < span class ="w " > </ span > run< span class =" w " > </ span > --rm< span class =" w " > </ span > < span class =" se " > \ </ span >
939- < span class =" w " > </ span > -u < span class =" w " > </ span > < span class =" s2 " > "</ span > < span class =" k " > $( </ span > id < span class =" w " > </ span > -u < span class =" k " > ) </ span > < span class =" s2 " > : </ span > < span class =" k " > $( </ span > id < span class =" w " > </ span > -g < span class =" k " > ) </ span > < span class =" s2 " > "</ span > < span class =" w " > </ span > < span class =" se " > \ </ span >
940- < span class =" w " > </ span > -v < span class =" w " > </ span > < span class =" s2 " > "<repo_root>:/src"</ span > < span class =" w " > </ span > -w < span class =" w " > </ span > / src< span class =" w " > </ span > < span class =" se " > \ </ span >
941- < span class =" w " > </ span > <image:tag>< span class =" w " > </ span > <entrypoint-or-cmd>< span class =" w " > </ span > <args...>
942- </ code > </ pre > </ div >
944+ < pre > < code class ="language-bash " > docker run --rm \
945+ -u "$(id -u):$(id -g) " \
946+ -v "<repo_root>:/src" -w / src \
947+ <image:tag> <entrypoint-or-cmd> <args...>
948+ </ code > </ pre >
943949< h4 id ="path-mapping_algorithm_portable "> Path-Mapping Algorithm (Portable)< a class ="headerlink " href ="#path-mapping_algorithm_portable " title ="Permanent link "> #</ a > </ h4 >
944950< ol >
945951< li > Normalize the caller’s path (host or dev container).</ li >
946952< li > Resolve to repo-relative (< code > rel_path</ code > ).</ li >
947953< li > Rewrite to container path: < code > /src/${rel_path}</ code > .</ li >
948954</ ol >
949955< h3 id ="sequence_diagram_build_run "> Sequence Diagram (Build + Run)< a class ="headerlink " href ="#sequence_diagram_build_run " title ="Permanent link "> #</ a > </ h3 >
950- < pre class ="mermaid "> < code > sequenceDiagram
951- participant Dev as Developer
952- participant CLI as Wrapper CLI
953- participant Eng as Docker Engine
954- participant C as Tool Container
955-
956- Dev->>CLI: run utility with options
957- CLI->>Eng: pull/build <image:tag>
958- Eng-->>CLI: image ready (cached if unchanged)
959- CLI->>Eng: run with mount /src, UID:GID, env
960- Eng->>C: start container
961- C->>C: execute utility
962- C-->>Eng: exit code + outputs on /src
963- Eng-->>CLI: container finished
964- CLI-->>Dev: exit code + logs</ code > </ pre >
956+ < p > < img alt ="" src ="../../../figs/blog4.1.png " /> </ p >
965957< h3 id ="workflow_diagram "> Workflow Diagram< a class ="headerlink " href ="#workflow_diagram " title ="Permanent link "> #</ a > </ h3 >
966- < pre class ="mermaid "> < code > graph TD
967- A[Developer Command] --> B[Wrapper Script]
968- B -->|Mounts repo + maps paths| C[Docker Container]
969- C -->|Runs tool with correct deps| D[Outputs to Repo]
970-
971- %% Optional styling
972- classDef cmd fill:#E3F2FD,stroke:#2196F3,color:#0D47A1,stroke-width:1px;
973- classDef wrap fill:#FFF8E1,stroke:#FFC107,color:#674100,stroke-width:1px;
974- classDef cont fill:#E8F5E9,stroke:#4CAF50,color:#1B5E20,stroke-width:1px;
975- classDef out fill:#F3E5F5,stroke:#9C27B0,color:#4A148C,stroke-width:1px;
976-
977- class A cmd;
978- class B wrap;
979- class C cont;
980- class D out;</ code > </ pre >
958+ < p > < img alt ="" src ="../../../figs/blog4.2.png " /> </ p >
981959< h3 id ="running_inside_containers "> Running Inside Containers< a class ="headerlink " href ="#running_inside_containers " title ="Permanent link "> #</ a > </ h3 >
982960< p > Many of our developers already work inside dev containers. Running a
983961containerized tool inside another container requires careful handling. There are
984962two approaches:</ p >
985963< ul >
986964< li > < strong > Children Containers (Docker-In-Docker):</ strong > One Container Launches
987- another. Flexible but requires elevated privileges.</ li >
965+ another. Flexible but requires elevated privileges.</ li >
988966< li > < strong > Sibling Containers:</ strong > the Dev Container Communicates with the Host’S
989- Docker engine to launch another container. Safer and more efficient, but
990- requires thoughtful mount management.</ li >
967+ Docker engine to launch another container. Safer and more efficient, but
968+ requires thoughtful mount management.</ li >
991969</ ul >
992970< p > At Causify, we < strong > prefer the sibling approach</ strong > for most workflows.</ p >
993971< h3 id ="testing_the_flow "> Testing the Flow< a class ="headerlink " href ="#testing_the_flow " title ="Permanent link "> #</ a > </ h3 >
994972< ul >
995973< li > Simulate Real Usage by Invoking the < strong > Same Wrapper</ strong > a Developer Would
996- use.</ li >
974+ use.</ li >
997975< li > Containers Run with Their < strong > Normal Entry Points</ strong > and Configurations.</ li >
998976< li > Assertions Check < strong > Outputs, Logs, or File Changes</ strong > .</ li >
999977< li > This Avoids Contrived Test Setups and Ensures Reliability.</ li >
@@ -1013,7 +991,7 @@ <h3 id="benefits_recap">Benefits Recap<a class="headerlink" href="#benefits_reca
1013991< li > < strong > Clean Environments:</ strong > No More Cluttered Local Installs.</ li >
1014992< li > < strong > Controlled Upgrades:</ strong > Images Are Version-Pinned and Reviewed.</ li >
1015993< li > < strong > Cross-Platform Stability:</ strong > Works Seamlessly Across Macos, Linux, and
1016- CI.</ li >
994+ CI.</ li >
1017995</ ul >
1018996< h3 id ="related_work "> Related Work< a class ="headerlink " href ="#related_work " title ="Permanent link "> #</ a > </ h3 >
1019997< p > When thinking about reproducible tooling, our Dockerized Executable flow is not
@@ -1023,26 +1001,26 @@ <h3 id="related_work">Related Work<a class="headerlink" href="#related_work" tit
10231001< h4 id ="uv_for_python_packages "> Uv for Python Packages< a class ="headerlink " href ="#uv_for_python_packages " title ="Permanent link "> #</ a > </ h4 >
10241002< ul >
10251003< li > < strong > What It Does:</ strong > < code > uv</ code > Is a Rust-Based Package Manager for Python. It
1026- installs both Python itself and project dependencies into isolated, cached
1027- environments.</ li >
1004+ installs both Python itself and project dependencies into isolated, cached
1005+ environments.</ li >
10281006< li > < strong > Philosophy:</ strong > Prevent "dependency hell" by Guaranteeing That Everyone on
1029- a team resolves to the same versions, without polluting the global
1030- environment.</ li >
1007+ a team resolves to the same versions, without polluting the global
1008+ environment.</ li >
10311009< li > < strong > Strengths:</ strong > Extremely Fast Installs, Lightweight, and Tailored
1032- specifically to Python workflows.</ li >
1010+ specifically to Python workflows.</ li >
10331011< li > < strong > Limitations:</ strong > Scope Is Narrow, It Only Solves Problems Within the Python
1034- ecosystem.</ li >
1012+ ecosystem.</ li >
10351013</ ul >
10361014< h4 id ="dockerized_executables_at_causify "> Dockerized Executables at Causify< a class ="headerlink " href ="#dockerized_executables_at_causify " title ="Permanent link "> #</ a > </ h4 >
10371015< ul >
10381016< li > < strong > What We Do:</ strong > Instead of Targeting One Language, We Containerize Any
1039- developer utility—from formatters to document converters to diagram renderers.</ li >
1017+ developer utility—from formatters to document converters to diagram renderers.</ li >
10401018< li > < strong > Philosophy:</ strong > Eliminate Setup Headaches by Running Tools in Docker
1041- images that include all their dependencies.</ li >
1019+ images that include all their dependencies.</ li >
10421020< li > < strong > Strengths:</ strong > Works Across Languages and Ecosystems, Consistent Behavior
1043- across laptops, dev containers, and CI.</ li >
1021+ across laptops, dev containers, and CI.</ li >
10441022< li > < strong > Limitations:</ strong > Requires Docker, and Images Are Heavier Than Python
1045- wheels. There is also a small first-run latency to pull/build the image.</ li >
1023+ wheels. There is also a small first-run latency to pull/build the image.</ li >
10461024</ ul >
10471025< h4 id ="comparison "> Comparison< a class ="headerlink " href ="#comparison " title ="Permanent link "> #</ a > </ h4 >
10481026< p > Both approaches are rooted in the same principle: tools should be easy to run,
@@ -1058,8 +1036,8 @@ <h4 id="why_we_still_need_both">Why We Still Need Both<a class="headerlink" href
10581036fills the gap.</ p >
10591037< h3 id ="technical_references "> Technical References< a class ="headerlink " href ="#technical_references " title ="Permanent link "> #</ a > </ h3 >
10601038< ul >
1061- < li > < code > helpers_root/ docs/tools/documentation_toolchain/all.notes_toolchain.how_to_guide.md</ code > </ li >
1062- < li > < code > helpers_root/ docs/tools/docker/all.dockerized_flow.explanation.md</ code > </ li >
1039+ < li > < a href =" https://github.com/causify-ai/helpers/blob/master/ docs/tools/documentation_toolchain/all.notes_toolchain.how_to_guide.md" > all.notes_toolchain.how_to_guide.md </ a > </ li >
1040+ < li > < a href =" https://github.com/causify-ai/helpers/blob/master/ docs/tools/docker/all.dockerized_flow.explanation.md" > all.dockerized_flow.explanation.md </ a > </ li >
10631041</ ul >
10641042< h3 id ="closing_thoughts "> Closing Thoughts< a class ="headerlink " href ="#closing_thoughts " title ="Permanent link "> #</ a > </ h3 >
10651043< p > If you’ve ever lost hours to installation issues, you know the frustration. With
0 commit comments