Skip to content

Instantly share code, notes, and snippets.

@pbiggar
Last active May 20, 2020 15:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pbiggar/cce9b958704c6cadd9597b717bc18c4d to your computer and use it in GitHub Desktop.
Save pbiggar/cce9b958704c6cadd9597b717bc18c4d to your computer and use it in GitHub Desktop.
using ocamlmerlin inside a docker container

We were able to make Spacemacs connect to ocamlmerlin in a Docker container. It definitely works in Spacemacs, and should work anywhere else. Please comment below if you can't make it work.

opam and ocamlmerlin are copies of the same file. ocp-indent, refmt, and other executables can be handled the same way.

The magic happens in run-in-docker. You most likely need to change the sed commands in fix_dirs_stdin and fix_dirs_stdout.

I've included a sample Dockerfile that we use with 4.04.2, note the env vars are important.

We keep all these scripts in our scripts/ directory, and always call them from the immediate parent direction. If you don't do that, I wouldn't expect these to work perfectly.

We're hiring: https://darklang.com

# Development dockerfile
# This is an image used to compile and test.
FROM ubuntu:17.04
## apt-get
# We pin the exact package version so that we don't have any surprises.
# However, sometimes the versions upgrade from under us and break the
# build. To fix that, you need the actual package version, which you can
# find by installing it directly:
# $ docker run <HASH> apt-get install mypackage
# Notes
# - replace <HASH> with a recent hash from the docker build output.
# - just use the package name, not the version.
# Deps:
# - apt-transport-https for npm
# - expect for unbuffer
# - libpcre3-dev for better-errors
# everything after "ocaml" for ocaml
RUN apt-get update && \
apt-get install -y software-properties-common \
python3.6 \
make \
m4 \
rsync \
git \
curl \
wget \
sudo \
ocaml \
opam \
libpq-dev \
libev-dev \
libgmp-dev \
pkg-config \
libcurl4-gnutls-dev \
libpcre3-dev \
&& rm -rf /var/lib/apt/lists/*
# dont run as root
RUN adduser --disabled-password --gecos '' user
RUN echo "user:user" | chpasswd && adduser user sudo
RUN chown -R user:user /home/user
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER user
WORKDIR /home/user
RUN mkdir bin
# Locales
RUN sudo locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
# Ocaml
RUN opam init --auto-setup
RUN opam switch 4.04.2
ENV PATH "/home/user/.opam/4.04.2/bin:$PATH"
ENV CAML_LD_LIBRARY_PATH "/home/user/.opam/4.04.2/lib/stublibs"
ENV MANPATH "/home/user/.opam/4.04.2/man:"
ENV PERL5LIB "/home/user/.opam/4.04.2/lib/perl5"
ENV OCAML_TOPLEVEL_PATH "/home/user/.opam/4.04.2/lib/toplevel"
ENV FORCE_BUILD 1
RUN opam update
RUN opam install ppx_deriving.4.1
RUN opam install core.v0.9.1
RUN opam install conf-libev lwt.3.1.0
RUN opam install yojson.1.3.3
RUN opam install postgresql.4.0.1
RUN opam install ppx_deriving_yojson.3.0
RUN opam install tls.0.8.0
RUN opam install cohttp-lwt-unix.0.99.0
RUN opam install ocurl.0.7.10
RUN opam install alcotest.0.8.1 # test
RUN opam install merlin.3.0.2 # dev
RUN opam install utop.2.0.1 # dev
RUN opam install ocp-indent.1.6.1 # dev
RUN opam install batteries.2.7.0
RUN opam install landmarks.1.1
# Environment
ENV TERM=xterm-256color
## ADD NEW PACKAGES HERE
# Doing otherwise will force a large recompile of the container for
# everyone
#!/bin/bash
# Created at http://ellenandpaulsnewstartup.com - we're hiring!
script=$(basename $0)
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
$DIR/run-in-docker "$script" ${@} <&0
#!/bin/bash
# Created at http://ellenandpaulsnewstartup.com - we're hiring!
script=$(basename $0)
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
$DIR/run-in-docker "$script" ${@} <&0
#!/bin/bash
set -euo pipefail
# Created at http://ellenandpaulsnewstartup.com - we're hiring!
function fix_dir_stdin {
sed -e "s!$DIR!/home/user/app!g"
}
function fix_dir_stdout {
sed -e "s!/home/user/app!$DIR!g" | sed -e "s!/home/user/.opam/.*/bin!$DIR/scripts!g"
}
# Replace any filenames with the in-container filenames (stdin)
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )"
ARGS=${@}
ARGS=$(echo ${ARGS} | fix_dir_stdin)
NAME=$(docker ps --latest --quiet)
if [ -t 0 ] ;
then
docker exec -it "${NAME}" ${ARGS} ;
else
# Replace any in-container filenames with host filesnames (stdout + stderr)
{ cat <&0 | fix_dir_stdin | docker exec -i "${NAME}" ${ARGS} 2>&1 1>&3 3>&- | fix_dir_stdout; } 3>&1 1>&2 | fix_dir_stdout
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment