on master help sign in
Improve developer experience with Docker

* Fix "Running as root is not recommended" message at container startup. See <https://github.com/ocaml/opam/issues/2575>. * Add Makefile targets to build and run Docker images, and 'make help' target. * Reduce number of layers in Dockerfile and improve build time. * Fix several bugs in Makefile which were causing spurious rebuilds. * Remove legacy extract.sh script. * Use HTTPS when downloading libmozjs. * Improve readability of Dockerfile and Makefile. Split out dependency installation into a separate Bash script. * Reduce verbosity of application and Docker builds. * Fix mistake in Cgo configuration for R, although R is still broken because using Cgo with libR requires Go 1.10.5 while Ubuntu Bionic only ships 1.10.4. See <https://github.com/golang/go/issues/27496>.

commitfbeaa14fd9e43c9bd77a3fb1f5080d5a61efdb0f authorRadon Rosborough <radon.neon@gmail.com> dateThu 13 Jun 2019, 16:19 (7 years ago) parenta67121f
8 files changed+142−105
Dockerfile+6−62 Dockerfile.dev+11 Makefile+31−13 README.md+35−22 extract.sh−3 languages/R/main.go+1−1 scripts/docker-install.sh+57 scripts/inject.sh+1−4
Dockerfile+6−62
@@ -1,69 +1,13 @@
11FROM ubuntu:bionic
22
3−RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
4− build-essential \
5− wget \
6− golang \
7− python-dev \
8− python3-dev \
9− liblua5.1-dev \
10− libreadline-dev \
11− ruby2.5-dev \
12− tcl-dev \
13− libnspr4-dev \
14− libffi-dev \
15− expect \
16− nodejs \
17− m4 \
18− software-properties-common \
19− emacs-nox
20−
21−RUN wget http://launchpadlibrarian.net/309343864/libmozjs185-dev_1.8.5-1.0.0+dfsg-7_amd64.deb && \
22− wget http://launchpadlibrarian.net/309343863/libmozjs185-1.0_1.8.5-1.0.0+dfsg-7_amd64.deb && \
23− dpkg -i libmozjs185*.deb && rm libmozjs185*.deb
24−
25−RUN wget https://julialang-s3.julialang.org/bin/linux/x64/1.1/julia-1.1.0-linux-x86_64.tar.gz && \
26− tar xf julia-1.1.0-linux-x86_64.tar.gz && \
27− cd julia-1.1.0 && \
28− cp -r bin/* /usr/bin/ && \
29− cp -r include/* /usr/include/ && \
30− cp -r lib/* /usr/lib/ && \
31− cp -r share/* /usr/share/ && \
32− cd .. && \
33− rm -rf julia-1.1.0-linux-x86_64.tar.gz julia-1.1.0
34−
35−# OCaml / Reason stuff
36−RUN add-apt-repository ppa:avsm/ppa && \
37− apt-get update && \
38− apt-get install ocaml opam -y && \
39− opam init -c ocaml-system -n --disable-sandboxing && \
40− eval `opam env` && \
41− echo "eval \`opam env\`" >> ~/.bashrc
3+COPY scripts/docker-install.sh /tmp/docker-install.sh
4+RUN /tmp/docker-install.sh
425
436RUN mkdir -p /gocode/src/github.com/replit/prybar
44−
45−ENV GOPATH=/gocode
46−ADD . /gocode/src/github.com/replit/prybar
7+COPY . /gocode/src/github.com/replit/prybar
478WORKDIR /gocode/src/github.com/replit/prybar
489
49−RUN cp languages/tcl/tcl.pc /usr/lib/pkgconfig/
10+ENV GOPATH=/gocode LC_ALL=C.UTF-8 PATH="/gocode/src/github.com/replit/prybar:$PATH"
5011
51−RUN make \
52− prybar-python2 \
53− prybar-python3 \
54− prybar-ruby \
55− prybar-lua \
56− prybar-spidermonkey \
57− prybar-nodejs \
58− prybar-julia \
59− prybar-tcl \
60− prybar-ocaml \
61− prybar-elisp
62−
63−ENV LC_ALL=C.UTF-8
64−
65−CMD bash
66−
67−# Local Variables:
68−# indent-tabs-mode: t
69−# End:
12+RUN cp languages/tcl/tcl.pc /usr/lib/pkgconfig/
13+RUN make
Dockerfile.devnew file+11
@@ -0,0 +1,11 @@
1+FROM ubuntu:bionic
2+
3+COPY scripts/docker-install.sh /tmp/docker-install.sh
4+RUN /tmp/docker-install.sh
5+
6+RUN mkdir -p /gocode/src/github.com/replit/prybar
7+WORKDIR /gocode/src/github.com/replit/prybar
8+
9+ENV GOPATH=/gocode LC_ALL=C.UTF-8 PATH="/gocode/src/github.com/replit/prybar:$PATH"
10+
11+RUN ln -s "$PWD/languages/tcl/tcl.pc" /usr/lib/pkgconfig/
Makefile+31−13
@@ -1,19 +1,37 @@
1−LANGDIR := ./languages
2−LANGS := $(shell ls $(LANGDIR))
3−BINS := $(addprefix prybar-,$(LANGS))
1+.PHONY: all
2+all: $(addprefix prybar-,$(filter-out R,$(shell ls languages))) ## Build all Prybar binaries
43
5−.PHONY: clean test all
4+# Avoid depending on the subdirectories of 'languages', because their
5+# mtimes are updated every time we build.
6+prybar-%: utils/*.go languages/%/* ## Build the Prybar binary for LANG
7+ @echo "build prybar-$(*)"
8+ @scripts/inject.sh $(*)
9+ @go generate languages/$(*)/main.go
10+ @go build -o prybar-$(*) ./languages/$(*)
11+ @rm -f languages/$(*)/generated_*.go
612
7−all: $(BINS)
13+.PHONY: docker
14+docker: ## Run a shell with Prybar inside Docker
15+ docker build . -f Dockerfile.dev -t prybar-dev
16+ docker run -it --rm -v "$$PWD:/gocode/src/github.com/replit/prybar" prybar-dev
817
9−prybar-%: ./languages/$(*) ./utils/* ./languages/$(*)/*
10− ./scripts/inject.sh $(*)
11− go generate ./languages/$(*)/main.go
12− go build -o prybar-$(*) ./languages/$(*)
13− rm ./languages/$(*)/generated_*.go
18+.PHONY: image
19+image: ## Build a Docker image with Prybar for distribution
20+ docker build . -t prybar
1421
15−test:
22+.PHONY: test
23+test: ## Run integration tests
1624 ./run_tests
1725
18−clean:
19− @rm -f ./prybar-* ./languages/*/generated_*.go
26+.PHONY: clean
27+clean: ## Remove build artifacts
28+ rm -f prybar-* languages/*/generated_*.go
29+
30+.PHONY: help
31+help: ## Show this message
32+ @echo "usage:" >&2
33+ @grep -h "[#]# " $(MAKEFILE_LIST) | \
34+ sed 's/^/ make /' | \
35+ sed 's/:[^#]*[#]# /|/' | \
36+ sed 's/%/LANG/' | \
37+ column -t -s'|' >&2
README.md+35−22
@@ -11,11 +11,11 @@ wanted them to all behave the same: run code and drop into a REPL!
1111
1212## How it works
1313
14−Prybar, written in Golang, maintains a common command-line interface
15−that calls into a select language backend. When possible, the language
16−backends are implemented using cgo and the language's C-bindings.
17−Otherwise, they make use of a small script written in the host
18−language which starts a Prybar-compatible REPL.
14+Prybar, written in [Golang](https://golang.org/), maintains a common
15+command-line interface that calls into a select language backend. When
16+possible, the language backends are implemented using cgo and the
17+language's C-bindings. Otherwise, they make use of a small script
18+written in the host language which starts a Prybar-compatible REPL.
1919
2020## Usage
2121
@@ -50,34 +50,47 @@ language which starts a Prybar-compatible REPL.
5050
5151## Build and run
5252
53+ % make help
54+ usage:
55+ make all Build all Prybar binaries
56+ make prybar-LANG Build the Prybar binary for LANG
57+ make docker Run a shell with Prybar inside Docker
58+ make image Build a Docker image with Prybar for distribution
59+ make test Run integration tests
60+ make clean Remove build artifacts
61+ make help Show this message
62+
5363Prybar uses Docker to make it easy to get started with development.
5464First, you must [install Docker](https://docs.docker.com/install/).
5565Then, run:
5666
57− $ docker build . -t prybar
67+ $ make docker
5868
5969to create a Docker image containing the Prybar code and all of its
60−dependencies. Building the image also includes compiling the Prybar
61−binaries (there is one for each supported language).
62−
63−To run the code in a Docker container:
70+dependencies, and launch a shell inside of it. The Prybar source
71+repository will be synchronized with the working directory of the
72+container's filesystem, so you only need to re-run `make docker` if
73+you change the Dockerfile or any of its scripts.
6474
65− $ docker run --rm -it prybar
66− # ./prybar-python3 -h
75+To build Prybar (this should be done inside `make docker` unless you
76+have installed all of Prybar's dependencies on your system), run
77+`make` or `make all`. Then the `prybar-LANG` binaries will be
78+available in the working directory and on `$PATH`, one for each
79+supported language `LANG` ([see the `languages` subdirectory of this
80+repository](languages)):
6781
68−The directory contains one `./prybar-LANG` binary for each supported
69−language `LANG` ([see the `languages` subdirectory of this
70−repository](languages)).
71−
72−When you make changes to the code, you must re-run `docker build` to
73−create a new Docker image before you can run it with `docker run`.
82+ $ prybar-python3 -h
7483
7584### Distribution
7685
77−The script `./extract.sh` can be used to compile and produce a tarball
78−containing all the Prybar binaries. You can run it on its own; it will
79−automatically compile a new Docker image if necessary and extract the
80−binaries from a running container.
86+Run `make image` to create a Docker image containing not only Prybar's
87+dependencies and source code but also its compiled binaries, which can
88+be embedded inside other Docker images by means of `COPY
89+--from=basicer/prybar`.
90+
91+This image is automatically built and deployed to [Docker
92+Hub](https://hub.docker.com/) every time a commit is merged to
93+`master`.
8194
8295## License
8396
extract.shdeleted−3
@@ -1,3 +0,0 @@
1−#!/bin/sh
2−docker build -t prybar .
3−docker run prybar bash -c 'tar -zc prybar-*' > prybar.tar.gz
languages/R/main.go+1−1
@@ -3,7 +3,7 @@ package main
33// USING_CGO
44
55/*
6−#cgo pkg-config: libr
6+#cgo pkg-config: libR
77#include <stdlib.h>
88#include <Rembedded.h>
99#include <RVersion.h>
scripts/docker-install.shnew file+57
@@ -0,0 +1,57 @@
1+#!/usr/bin/env bash
2+
3+set -e
4+set -o pipefail
5+
6+export DEBIAN_FRONTEND=noninteractive
7+
8+apt-get update
9+apt-get install -y software-properties-common
10+add-apt-repository ppa:avsm/ppa
11+
12+packages="
13+
14+bsdmainutils
15+build-essential
16+emacs-nox
17+expect
18+golang
19+libffi-dev
20+liblua5.1-dev
21+libnspr4-dev
22+libreadline-dev
23+m4
24+nodejs
25+ocaml
26+opam
27+python-dev
28+python3-dev
29+ruby2.5-dev
30+tcl-dev
31+wget
32+
33+"
34+
35+apt-get install -y $packages
36+rm -rf /var/lib/apt/lists/*
37+
38+wget -nv https://launchpadlibrarian.net/309343863/libmozjs185-1.0_1.8.5-1.0.0+dfsg-7_amd64.deb
39+wget -nv https://launchpadlibrarian.net/309343864/libmozjs185-dev_1.8.5-1.0.0+dfsg-7_amd64.deb
40+dpkg -i libmozjs185*.deb
41+rm libmozjs185*.deb
42+
43+wget https://julialang-s3.julialang.org/bin/linux/x64/1.1/julia-1.1.0-linux-x86_64.tar.gz
44+tar -xf julia-1.1.0-linux-x86_64.tar.gz
45+cp -R julia-1.1.0/bin/* /usr/bin/
46+cp -R julia-1.1.0/include/* /usr/include/
47+cp -R julia-1.1.0/lib/* /usr/lib/
48+cp -R julia-1.1.0/share/* /usr/share/
49+rm -rf julia-1.1.0*
50+
51+opam init -c ocaml-system -n --disable-sandboxing
52+cat <<"EOF" >> "$HOME/.bashrc"
53+export OPAMROOTISOK=1
54+eval "$(opam env)"
55+EOF
56+
57+rm /tmp/docker-install.sh
scripts/inject.sh+1−4
@@ -1,10 +1,7 @@
11#!/bin/bash
22
3−if grep "USING_CGO" ./languages/$1/main.go; then
3+if grep -q "USING_CGO" ./languages/$1/main.go; then
44 cp inject_claunch.go ./languages/$1/generated_launch.go
55else
66 cp inject_elaunch.go ./languages/$1/generated_launch.go
77fi
8−
9−
10−