Skip to content

Adds support for R, tidied Dockerfile #198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jan 27, 2024
153 changes: 95 additions & 58 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
# Build statge
# Build stage
FROM ubuntu:22.04 as builder
ARG DEBIAN_FRONTEND=noninteractive


# Stage-wide dependencies
RUN apt update && \
apt install --no-install-recommends --no-install-suggests --yes \
build-essential \
ca-certificates \
curl


# Install Java 21.x
# http://jdk.java.net/21/
RUN cd /tmp && \
if [ $(uname -m) = "x86_64" ]; then ARCH="x64"; else ARCH="aarch64"; fi && \
curl --remote-name https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-${ARCH}_bin.tar.gz && \
tar xzf openjdk-21.0.2_linux-${ARCH}_bin.tar.gz && \
rm --force openjdk-21.0.2_linux-${ARCH}_bin.tar.gz && \
mv jdk-21.0.2 /opt/jdk && \
mkdir --parent /opt/bin && \
ln --symbolic /opt/jdk/bin/* /opt/bin/ && \
chmod a+rx /opt/bin/*


# Install Node.js 21.x
# https://nodejs.dev/en/download/
# https://github.com/tj/n#installation
RUN curl --location https://github.com/raw/tj/n/master/bin/n --output /usr/local/bin/n && \
chmod a+x /usr/local/bin/n && \
n 21.6.1


# Install Node.js packages
RUN npm install --global \
http-server


# Patch index.js in http-server
COPY index.js.patch /tmp
RUN cd /usr/local/lib/node_modules/http-server/lib/core/show-dir && \
patch index.js < /tmp/index.js.patch && \
rm --force /tmp/index.js.patch


# Suggested build environment for Python, per pyenv, even though we're building ourselves
# https://github.com/pyenv/pyenv/wiki#suggested-build-environment
RUN apt update && \
apt install --no-install-recommends --no-install-suggests --yes \
curl ca-certificates build-essential git \
build-essential ca-certificates curl git \
libssl-dev libbz2-dev libreadline-dev libsqlite3-dev \
llvm libncursesw5-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \
make tk-dev unzip wget xz-utils zlib1g-dev
Expand All @@ -16,7 +57,7 @@ RUN apt update && \
# Install Python 3.11.x
# https://www.python.org/downloads/
RUN cd /tmp && \
curl https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz --output Python-3.11.7.tgz && \
curl --remote-name https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tgz && \
tar xzf Python-3.11.7.tgz && \
rm --force Python-3.11.7.tgz && \
cd Python-3.11.7 && \
Expand All @@ -31,14 +72,32 @@ RUN cd /tmp && \
pip3 install --no-cache-dir --upgrade pip


# Install R
# https://docs.posit.co/resources/install-r-source/#build-and-install-r
# https://cran.rstudio.com/src/base/R-4/
RUN sed --in-place "/^#.*deb-src.*universe$/s/^# //g" /etc/apt/sources.list && \
apt update && \
apt build-dep --yes r-base && \
cd /tmp && \
curl --remote-name https://cran.rstudio.com/src/base/R-4/R-4.3.2.tar.gz && \
tar xzf R-4.3.2.tar.gz && \
rm --force R-4.3.2.tar.gz && \
cd R-4.3.2 && \
./configure --enable-memory-profiling --enable-R-shlib && \
make && \
make install && \
cd .. && \
rm --force --recursive R-4.3.2


# Install Ruby 3.2.x
# https://www.ruby-lang.org/en/downloads/
RUN apt update && \
apt install --no-install-recommends --no-install-suggests --yes \
autoconf \
libyaml-dev && \
apt clean && \
rm -rf /var/lib/apt/lists/* && \
rm --force --recursive /var/lib/apt/lists/* && \
cd /tmp && \
curl https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.2.tar.gz --output ruby-3.2.2.tar.gz && \
tar xzf ruby-3.2.2.tar.gz && \
Expand Down Expand Up @@ -66,64 +125,33 @@ RUN gem install --no-document \
# https://www.sqlite.org/howtocompile.html#compiling_the_command_line_interface
COPY shell.c.patch /tmp
RUN cd /tmp && \
curl --remote-name https://www.sqlite.org/2023/sqlite-amalgamation-3440200.zip && \
unzip sqlite-amalgamation-3440200.zip && \
rm --force sqlite-amalgamation-3440200.zip && \
cd sqlite-amalgamation-3440200 && \
curl --remote-name https://www.sqlite.org/2024/sqlite-amalgamation-3450000.zip && \
unzip sqlite-amalgamation-3450000.zip && \
rm --force sqlite-amalgamation-3450000.zip && \
cd sqlite-amalgamation-3450000 && \
patch shell.c < /tmp/shell.c.patch && \
gcc -D HAVE_READLINE -D SQLITE_DEFAULT_FOREIGN_KEYS=1 -D SQLITE_OMIT_DYNAPROMPT=1 shell.c sqlite3.c -lpthread -ldl -lm -lreadline -lncurses -o /usr/local/bin/sqlite3 && \
cd .. && \
rm --force --recursive sqlite-amalgamation-3440200 && \
rm --force --recursive sqlite-amalgamation-3450000 && \
rm --force /tmp/shell.c.patch


# Install Java 21.x
# http://jdk.java.net/21/
RUN cd /tmp && \
curl --remote-name https://download.java.net/java/GA/jdk21.0.1/415e3f918a1f4062a0074a2794853d0d/12/GPL/openjdk-21.0.1_linux-x64_bin.tar.gz && \
tar xzf openjdk-21.0.1_linux-x64_bin.tar.gz && \
rm --force openjdk-21.0.1_linux-x64_bin.tar.gz && \
mv jdk-21.0.1 /opt/ && \
mkdir --parent /opt/bin && \
ln --symbolic /opt/jdk-21.0.1/bin/* /opt/bin/ && \
chmod a+rx /opt/bin/*


# Install Node.js 21.x
# https://nodejs.dev/en/download/
# https://github.com/tj/n#installation
RUN curl --location https://github.com/raw/tj/n/master/bin/n --output /usr/local/bin/n && \
chmod a+x /usr/local/bin/n && \
n 21.5.0


# Install GitHub CLI
# https://github.com/cli/cli/blob/trunk/docs/install_linux.md#debian-ubuntu-linux-raspberry-pi-os-apt
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
apt update && \
apt install gh --no-install-recommends --no-install-suggests --yes


# Final stage
FROM ubuntu:22.04
LABEL maintainer="[email protected]"
ARG DEBIAN_FRONTEND=noninteractive


# Copy files from builder
COPY --from=builder /usr /usr
COPY --from=builder /opt /opt
COPY --from=builder /usr/local /usr/local


# Avoid "delaying package configuration, since apt-utils is not installed"
# Install locales
RUN apt update && \
apt install --no-install-recommends --no-install-suggests --yes \
apt-utils \
curl \
ca-certificates \
locales && \
locale-gen \
en_US.utf8 \
Expand All @@ -145,16 +173,18 @@ RUN apt update && \
ENV LANG=C.UTF-8


# Install CS50, Ubuntu, and Python packages
RUN curl https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh | bash && \
apt update && \
# Install Ubuntu packages
RUN apt update && \
apt upgrade --yes && \
apt install --no-install-recommends --no-install-suggests --yes \
astyle \
bash-completion \
build-essential `# dpkg-dev, libc, gcc, g++, make, etc.`\
ca-certificates \
clang \
coreutils `# For fold` \
cowsay \
curl \
dos2unix \
dnsutils `# For nslookup` \
fonts-noto-color-emoji `# For render50` \
Expand All @@ -163,7 +193,7 @@ RUN curl https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh |
git-lfs \
jq \
less \
libcs50 \
liblapack3 `# For R` \
libmagic-dev `# For style50` \
libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0 `# For render50` \
libyaml-0-2 `# Runtime package for gem` \
Expand All @@ -178,9 +208,19 @@ RUN curl https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh |
unzip \
valgrind \
vim \
wget \
zip && \
apt clean && \
pip3 install --no-cache-dir \
apt clean


# Install CS50 library
RUN curl https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh | bash && \
apt update && \
apt install --yes libcs50


# Install Python packages
RUN pip3 install --no-cache-dir \
autopep8 \
black \
"check50<4" \
Expand All @@ -196,16 +236,13 @@ RUN curl https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh |
"submit50<4"


# Install Node.js packages
RUN npm install --global \
[email protected] `# Fixate for patch`


# Patch index.js in http-server
COPY index.js.patch /tmp
RUN cd /usr/local/lib/node_modules/http-server/lib/core/show-dir && \
patch index.js < /tmp/index.js.patch && \
rm --force /tmp/index.js.patch
# Install GitHub CLI (after builder stage, because writes to /usr/share)
# https://github.com/cli/cli/blob/trunk/docs/install_linux.md#debian-ubuntu-linux-raspberry-pi-os-apt
RUN curl --fail --location --show-error --silent https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
apt update && \
apt install --no-install-recommends --no-install-suggests --yes gh


# Copy files to image
Expand Down Expand Up @@ -245,4 +282,4 @@ ONBUILD USER ubuntu
# Set user
USER ubuntu
WORKDIR /home/ubuntu
ENV WORKDIR=/home/ubuntu
ENV WORKDIR=/home/ubuntu
1 change: 1 addition & 0 deletions etc/profile.d/cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if [ "$(whoami)" != "root" ]; then
alias mv="mv -i"
alias pip="pip --no-cache-dir"
alias python="python -q"
alias R="R --vanilla"
alias rm="rm -i"
alias sudo="sudo " # Trailing space enables elevated command to be an alias

Expand Down
9 changes: 2 additions & 7 deletions shell.c.patch
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# diff shell.c shell_modified.c > shell.c.patch
29321,29323c29321,29323
< oputf("SQLite version %s %.19s%s\n" /*extra-version-info*/
29438,29440d29437
< sputf(stdout, "SQLite version %s %.19s%s\n" /*extra-version-info*/
< "Enter \".help\" for usage hints.\n",
< sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);
---
> //oputf("SQLite version %s %.19s%s\n" /*extra-version-info*/
> // "Enter \".help\" for usage hints.\n",
> // sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);