├── .gitignore ├── Makefile ├── README.md ├── infrastructure ├── README.md └── upstart │ ├── containers │ ├── docker-instance.conf │ └── docker-manager.conf ├── sagemath-base └── Dockerfile ├── sagemath-develop ├── sagemath-jupyter └── Dockerfile ├── sagemath-local-develop └── Dockerfile ├── sagemath-patchbot └── Dockerfile └── sagemath ├── Dockerfile └── scripts ├── install_sage.sh └── post_install_sage.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Files generated by the Makefile 2 | .logs 3 | .stamps 4 | 5 | # Editor files 6 | *.sw[po] 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | 3 | # Images and image-specific steps 4 | BASE_IMAGES=sagemath-base 5 | DEVELOP_IMAGES=sagemath-develop sagemath-patchbot 6 | RELEASE_IMAGES=sagemath sagemath-jupyter 7 | IMAGES=$(DEVELOP_IMAGES) $(RELEASE_IMAGES) 8 | 9 | TESTED_IMAGES=sagemath sagemath-develop 10 | NON_TESTED_IMAGES=sagemath-patchbot sagemath-jupyter 11 | 12 | BUILD_IMAGES=$(addprefix build-,$(IMAGES)) 13 | BUILD_BASE_IMAGES=$(addprefix build-,$(BASE_IMAGES)) 14 | BUILD_RELEASE_IMAGES=$(addprefix build-,$(RELEASE_IMAGES)) 15 | BUILD_DEVELOP_IMAGES=$(addprefix build-,$(DEVELOP_IMAGES)) 16 | TEST_IMAGES=$(addprefix test-,$(TESTED_IMAGES)) 17 | PUSH_IMAGES=$(addprefix push-,$(IMAGES)) 18 | 19 | .PHONY: all build push docker-clean sagemath-base sagemath-local-develop \ 20 | $(BASE_IMAGES) $(IMAGES) \ 21 | $(BUILD_IMAGES) $(BUILD_RELEASE_IMAGES) $(BUILD_DEVELOP_IMAGES) \ 22 | $(TEST_IMAGES) $(PUSH_IMAGES) 23 | 24 | # Directories 25 | STAMP_DIR=.stamps 26 | LOG_DIR=.logs 27 | 28 | # Stamp files 29 | BUILD_BASE_IMAGES_S=$(addprefix $(STAMP_DIR)/,$(BUILD_BASE_IMAGES)) 30 | BUILD_RELEASE_IMAGES_S=$(addprefix $(STAMP_DIR)/,$(BUILD_RELEASE_IMAGES)) 31 | BUILD_DEVELOP_IMAGES_S=$(addprefix $(STAMP_DIR)/,$(BUILD_DEVELOP_IMAGES)) 32 | TEST_IMAGES_S=$(addprefix $(STAMP_DIR)/,$(TEST_IMAGES)) 33 | NON_TEST_IMAGES_S=$(addprefix $(STAMP_DIR)/test-,$(NON_TESTED_IMAGES)) 34 | PUSH_IMAGES_S=$(addprefix $(STAMP_DIR)/,$(PUSH_IMAGES)) 35 | STAMPS=$(BUILD_BASE_IMAGES_S) $(BUILD_RELEASE_IMAGES_S) \ 36 | $(BUILD_DEVELOP_IMAGES_S) $(TEST_IMAGES_S) $(PUSH_IMAGES_S) 37 | 38 | SAGE_GIT_URL=git://git.sagemath.org/sage.git 39 | # Rather than hard-coding a default, this variable should always be specified 40 | # when building a non-develop version. 41 | SAGE_VERSION ?= 42 | TAG_LATEST ?= 0 43 | 44 | # Additional configuration 45 | # Supplies the number of CPUs on the build machine, but no more than 8 46 | N_CORES ?= $(shell N=$$(cat /proc/cpuinfo | grep '^processor' | wc -l); \ 47 | [ $$N -gt 8 ] && echo 8 || echo $$N) 48 | 49 | ################################ Subroutines ################################## 50 | 51 | check_defined = \ 52 | $(if $(value $(strip $1)),,$(error Undefined $(strip $1)$(if $2, ($(strip $2))))) 53 | 54 | get_git_hash = \ 55 | $$(git ls-remote --heads $(SAGE_GIT_URL) $1 | \ 56 | grep 'refs/heads/$(strip $1)' | awk '{print $$1}') 57 | 58 | get_image_hash = \ 59 | $$(docker images -q --no-trunc $1) 60 | 61 | # Run the tests for sage--the first argument is the image name 62 | # This runs the tests up to two times: Once normally, and then if there 63 | # are failures once more with the --failed flag. 64 | # This is because there are some tests that tend to fail the first time the 65 | # test suite is run. These tests should probably be fixed, but in the meantime 66 | # this is a reasonable workaround. 67 | sage_run = \ 68 | $(if $(findstring -develop,$1),,\ 69 | $(call check_defined, SAGE_VERSION, Sage version to test)) \ 70 | docker run --rm \ 71 | sagemath/$(strip $1)$(if $(findstring -develop,$1),,:$(SAGE_VERSION)) \ 72 | $2 73 | 74 | sage_test = \ 75 | $(call sage_run, $1, bash -c 'sage -t -p 0 -a --long || sage -t -p 0 -a --long --failed') 76 | 77 | # Write command stdout/err to a logfile in $(LOG_DIR)/ 78 | # $1: The command to run 79 | # $2: The base name of the logfile 80 | log = $1 2>&1 | tee $(LOG_DIR)/$(strip $2).log ; test $${PIPESTATUS[0]} -eq 0 81 | 82 | ############################## Top-level Targets ############################## 83 | 84 | all: $(IMAGES) 85 | 86 | release: sagemath sagemath-jupyter 87 | 88 | sagemath: sagemath-base 89 | 90 | sagemath-develop: sagemath-base 91 | 92 | sagemath-jupyter: sagemath 93 | 94 | sagemath-patchbot: sagemath-develop 95 | 96 | build: $(BUILD_IMAGES) 97 | 98 | test: $(TEST_IMAGES) 99 | 100 | push: $(PUSH_IMAGES) 101 | 102 | ############################### Cleanup Targets ############################### 103 | 104 | # Refs: 105 | # - https://www.calazan.com/docker-cleanup-commands/ 106 | # - http://stackoverflow.com/questions/17236796/how-to-remove-old-docker-containers 107 | 108 | docker-clean: 109 | @echo "Remove all non running containers" 110 | -docker rm `docker ps -q -f status=exited` 111 | @echo "Delete all untagged/dangling () images" 112 | -docker rmi `docker images -q -f dangling=true` 113 | 114 | $(addprefix clean-,$(BASE_IMAGES) $(IMAGES)): 115 | rm -f $(STAMP_DIR)/*-$(subst clean-,,$@) 116 | 117 | clean-all: $(addprefix clean-,$(BASE_IMAGES) $(IMAGES)) 118 | 119 | ################################# Main Rules ################################## 120 | 121 | $(BASE_IMAGES): %: $(STAMP_DIR)/build-% 122 | $(IMAGES): %: $(STAMP_DIR)/push-% 123 | $(BUILD_BASE_IMAGES) $(BUILD_IMAGES) $(TEST_IMAGES) $(PUSH_IMAGES): %: $(STAMP_DIR)/% 124 | 125 | $(STAMPS): | $(STAMP_DIR) $(LOG_DIR) 126 | 127 | $(BUILD_BASE_IMAGES_S): $(STAMP_DIR)/build-%: %/Dockerfile 128 | @echo Building $@ image 129 | $(call log, time docker build $(DOCKER_BUILD_FLAGS) \ 130 | --tag=sagemath/$* $*, \ 131 | build-$*) 132 | echo $(call get_image_hash,sagemath/$*) > $@ 133 | 134 | # Build all release images 135 | $(BUILD_RELEASE_IMAGES_S): $(STAMP_DIR)/build-%: %/Dockerfile 136 | @echo Building sagemath/$* 137 | $(call check_defined, SAGE_VERSION, Sage version to build) 138 | $(call log, time docker build $(DOCKER_BUILD_FLAGS) \ 139 | --tag="sagemath/$*:$(SAGE_VERSION)" \ 140 | --build-arg SAGE_BRANCH=$(SAGE_VERSION) $*, \ 141 | build-$*) 142 | ifeq ($(TAG_LATEST),1) 143 | docker tag "sagemath/$*:$(SAGE_VERSION)" "sagemath/$*:latest" 144 | endif 145 | echo $(call get_image_hash,sagemath/$*:$(SAGE_VERSION)) > $@ 146 | 147 | # Builds the sagemath-develop and sagemath-patchbot images 148 | $(BUILD_DEVELOP_IMAGES_S): $(STAMP_DIR)/build-%: %/Dockerfile 149 | @echo Building sagemath/$* 150 | $(call log, time docker build $(DOCKER_BUILD_FLAGS) \ 151 | --tag="sagemath/$*" \ 152 | --build-arg N_CORES=$(N_CORES) \ 153 | --build-arg SAGE_BRANCH=develop \ 154 | --build-arg SAGE_COMMIT=$(call get_git_hash, develop) $*,\ 155 | build-$*) 156 | echo $(call get_image_hash,sagemath/$*) > $@ 157 | 158 | # Note: Don't test patchbot images since running the tests is part of building 159 | # the image itself. 160 | $(TEST_IMAGES_S): $(STAMP_DIR)/test-%: $(STAMP_DIR)/build-% 161 | @echo "Testing $*" 162 | $(call log, $(call sage_test, $*), test-$*) 163 | @echo "All tests passed" 164 | touch $@ 165 | 166 | $(NON_TEST_IMAGES_S): $(STAMP_DIR)/test-%: $(STAMP_DIR)/build-% 167 | touch $@ 168 | 169 | $(PUSH_IMAGES_S): $(STAMP_DIR)/push-%: $(STAMP_DIR)/build-% $(STAMP_DIR)/test-% 170 | @echo Pushing $* 171 | $(if $(or $(findstring -develop,$*),$(findstring -patchbot,$*)),\ 172 | docker push "sagemath/$*",\ 173 | $(call check_defined, SAGE_VERSION, Sage version to push) \ 174 | docker push "sagemath/$*:$(SAGE_VERSION)") 175 | ifeq ($(TAG_LATEST),1) 176 | $(if $(findstring -develop,$*),,docker push "sagemath/$*:latest") 177 | endif 178 | touch $@ 179 | 180 | sagemath-local-develop: %: %/Dockerfile 181 | @echo Building $@ image 182 | time docker build $(DOCKER_BUILD_FLAGS) --tag=sagemath/$@ $(dir $<) 2>&1 | tee $<.log 183 | 184 | # For all images this generates rules for dependencies for their Dockerfile 185 | # so that if any of the files in build context are changed the Dockerfile is 186 | # updated as well. 187 | define DOCKERFILE_RULE_TEMPLATE 188 | $(1)/Dockerfile: $$(shell find $(1)/ -type f -a ! -name Dockerfile) 189 | touch $$@ 190 | endef 191 | $(foreach image,$(BASE_IMAGES) $(IMAGES),$(eval $(call DOCKERFILE_RULE_TEMPLATE,$(image)))) 192 | 193 | $(STAMP_DIR) $(LOG_DIR): 194 | mkdir $@ 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This repository is obsolete. Docker images are created by [GitLab CI scripts](https://github.com/sagemath/sage/blob/master/.gitlab-ci.yml) from a [Dockerfile](https://github.com/sagemath/sage/blob/master/docker/Dockerfile) that is in the main [sagemath/sage](https://github.com/sagemath/sage) repository now.** 2 | 3 | # Containers for SageMath & friends 4 | 5 | This repository contains a collection of Dockerfiles and supporting files 6 | for building various containers for SageMath and its components (GAP, 7 | Singular, PARI/GP, ...). 8 | 9 | The containers are available on [dockerhub](https://hub.docker.com/u/sagemath/). 10 | 11 | ## Tag format 12 | 13 | Each image is tagged with the version of SageMath installed in that image (e.g. 14 | 8.0). 15 | 16 | Tags with a version like `X.Y-N` represent revisions to the image itself i.e. 17 | changes that were made to the Dockerfile it was built from. For example while 18 | `sagemath:8.0` is the first image to contain SageMath 8.0, `sagemath:8.0-1` is 19 | the first revised SageMath 8.0 image. 20 | 21 | ## [sagemath/sagemath](sagemath/Dockerfile) (roughly 3.6 GB) 22 | 23 | This container contains a basic installation of the latest version of 24 | SageMath, built from sources on the latest Ubuntu. Commands are run as 25 | the Sage user. The SageMath distribution includes several programs 26 | like GAP, Singular, PARI/GP, R, ... which are available in the path. 27 | 28 | ### Installation 29 | 30 | docker pull sagemath/sagemath 31 | 32 | or simply continue to the next step. 33 | 34 | ### Running Sage & co with a console interface 35 | 36 | To run Sage: 37 | 38 | docker run -it sagemath/sagemath 39 | 40 | Other software included in this image can be run similarly: 41 | 42 | docker run -it sagemath/sagemath gap 43 | 44 | docker run -it sagemath/sagemath gp # PARI/GP 45 | 46 | docker run -it sagemath/sagemath maxima 47 | 48 | docker run -it sagemath/sagemath R 49 | 50 | docker run -it sagemath/sagemath singular 51 | 52 | ### Running the notebook interfaces 53 | 54 | To run the Jupyter Notebook interface (for Sage, ...): 55 | 56 | docker run -p 8888:8888 sagemath/sagemath-jupyter 57 | 58 | Alternatively, to run the legacy Sage notebook server: 59 | 60 | docker run -p 8080:8080 sagemath/sagemath sage -notebook 61 | 62 | You can then connect your web browser to the printed out typically, namely 63 | http://localhost:8888 for the Jupyter notebook and http://localhost:8080 for 64 | the legacy notebook. For the legacy notebook the webbrowser will ask for a 65 | login and password which are respectively `admin` and `sage`. 66 | 67 | **Note** Running the sagemath-jupyter container is equivalent to running the 68 | `sagemath/sagemath` base docker container with the following command: 69 | 70 | docker run -p 127.0.0.1:8888:8888 sagemath/sagemath sage -notebook=jupyter --no-browser --ip='*' --port=8888 71 | 72 | The `--ip` option is required by the Jupyter notebook to allow connections to 73 | the notebook through the Docker network. 74 | 75 | ### Rebuilding the container 76 | 77 | Prequisites: network access to download Sage (http/https) 78 | 79 | docker build --tag="sagemath/sagemath" sagemath 80 | 81 | ## [sagemath/sagemath-develop](sagemath-develop/Dockerfile) 82 | 83 | This container is similar to the previous one, except that SageMath is built 84 | from the latest unstable release version of Sage, retrieved by cloning the 85 | develop branch from github. 86 | 87 | TODO: include git-trac 88 | 89 | To download and start it: 90 | 91 | docker run -it sagemath/sagemath-develop 92 | 93 | ### Rebuilding the container 94 | 95 | docker build --tag="sagemath/sagemath-develop" sagemath-develop 96 | 97 | ## [sagemath/sagemath-jupyter](sagemath-jupyter/Dockerfile) 98 | 99 | If you want to have a container already set up for the Jupyter enviroment, 100 | you can use sagemath/sagemath-jupyter. It is based on sagemath/sagemath. 101 | 102 | docker run -p 8888:8888 sagemath/sagemath-jupyter 103 | 104 | makes the Jupyter notebook accessible via `localhost:8888`, while 105 | 106 | docker run sagemath/sagemath-jupyter 107 | 108 | makes it accessible under the container's ip address on port `8888`. You can 109 | see the ip address of the container using `docker inspect`. This is useful if 110 | you want to have more than one notebook server running. Typically this will 111 | be something like: 112 | 113 | 172.17.0.1 114 | 115 | where the fourth field may be incremented depending on the number of running 116 | containers on the host. 117 | 118 | ### Rebuilding the container 119 | 120 | docker build --tag="sagemath/sagemath-jupyter" sagemath-jupyter 121 | 122 | ## [sagemath/sagemath-patchbot](sagemath-patchbot/Dockerfile) 123 | 124 | This container, built on top of sagemath-develop, is meant to run 125 | instances of the [Sage patchbot](http://patchbot.sagemath.org/) 126 | running securely in a sandbox, to ensure that the untrusted code it 127 | fetches and run cannot harm the host machine. 128 | 129 | ### Starting the patchbot: 130 | 131 | docker run -t --name="patchbot" -d sagemath/sagemath-patchbot 132 | pid=$(docker inspect -f '{{.State.Pid}}' patchbot ) 133 | ip=$(docker inspect -f '{{.NetworkSettings.IPAddress}}' patchbot ) 134 | trac_ip=$(getent hosts trac.sagemath.org | awk '{ print $1 }') 135 | patchbot_ip=$(getent hosts patchbot.sagemath.org | awk '{ print $1 }') 136 | nsenter -t $pid -n iptables -A FORWARD -s ${ip} -d ${trac_ip} -j ACCEPT 137 | nsenter -t $pid -n iptables -A FORWARD -s ${ip} -d ${patchbot_ip} -j ACCEPT 138 | nsenter -t $pid -n iptables -A FORWARD -s ${ip} -j REJECT --reject-with icmp-host-prohibited 139 | 140 | while true; docker run --tty=true --rm=true sagemath/sagemath-patchbot; done 141 | 142 | ### Rebuilding the container: 143 | 144 | docker build --tag="sagemath/sagemath-patchbot" sagemath-patchbot 145 | 146 | ## sagemath/sagemath-fat (planned) 147 | 148 | sagemath/sagemath with latex, the commonly used (GAP) packages, etc. 149 | 150 | ## sagemath/sagemath-fat-jupyter (planned) 151 | 152 | Same as sagemath-jupyter, but based on sagemath-fat 153 | -------------------------------------------------------------------------------- /infrastructure/README.md: -------------------------------------------------------------------------------- 1 | # Infrastructure in Paris Sud for building the images 2 | 3 | We have a virtual machine on the Paris Sud University cloud for building 4 | images. This directory contains documentation and config files for that 5 | infrastructure, though may be useful for recreating it elsewhere as well. 6 | 7 | ## Steps to recreate that virtual machine 8 | 9 | - Connect https://keystone.lal.in2p3.fr/ 10 | - Login with stratuslab domain and your credentials 11 | - Flavor: os.16, image: Ubuntu 14.04 12 | - *Whatever you do:* Make sure your kernel is not affected by this issue: 13 | https://github.com/moby/moby/issues/18180; recent versions in Debian and 14 | Ubuntu are all up to date on this and are not affected. So make sure to 15 | grab the latest kernel updates just to be sure. 16 | 17 | - Connect on the machine and run the following commands: 18 | 19 | ssh ubuntu@... 20 | sudo su - 21 | 22 | # TODO: update this for openstack; not needed with the current default disk space 23 | # mkdir /var/lib/docker 24 | # echo /dev/vdc /var/lib/docker ext4 errors=remount-ro 0 1 >> /etc/fstab 25 | 26 | # Taken from https://docs.docker.com/engine/installation/linux/ubuntulinux/ 27 | apt-get install -y apt-transport-https ca-certificates software-properties-common build-essential 28 | apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 29 | # This does not quite work; one gets "... trusty main" in /etc/sources.list instead of "ubuntu-trusty main" 30 | # add-apt-repository https://apt.dockerproject.org/repo 31 | 32 | echo deb https://apt.dockerproject.org/repo ubuntu-trusty main > /etc/apt/sources.list.d/docker.list 33 | apt-get update 34 | apt-get install -y apparmor linux-image-extra-$(uname -r) docker-engine git make 35 | groupadd docker 36 | usermod -aG docker ubuntu 37 | 38 | - The Sage patchbot container currently has an issue where the patchbot 39 | command will refuse to run if there is not a certain amount of disk space 40 | available. However, the default size of Docker container images is not 41 | large enough for the patchbot container. So we increase that limit before 42 | restarting the docker service: 43 | 44 | echo 'DOCKER_OPTS="--storage-opt dm.basesize=20G"' >> /etc/default/docker 45 | service docker restart 46 | 47 | - log-out completely (for ubuntu's docker permission) / log-in again as ubuntu 48 | 49 | - Reconnect on the machine and run the following commands: 50 | 51 | ssh ubuntu@... 52 | docker run hello-world 53 | 54 | git clone https://github.com/sagemath/docker-images.git 55 | cd docker-images 56 | make # you probably want to run this with screen or byobu 57 | 58 | ## Set up the Docker container manager Upstart service 59 | 60 | Ubuntu is in the process of switching over to systemd, but the version of 61 | Ubuntu we are running currently uses Upstart. We are using a service 62 | called "docker-manager" picked up from here: 63 | 64 | https://gist.github.com/ismell/6281967 65 | 66 | This makes it easy to create Upstart services for individual Docker containers 67 | (we will use this to make a service for running the sagemath-patchbot image in 68 | a container). I modified it just slightly so that the `/etc/docker/containers` 69 | file allows additional options to be passed to `docker run` when creating the 70 | container. 71 | 72 | For starters just copy `upstart/*.conf` into `/etc/init`: 73 | 74 | sudo cp upstart/*.conf /etc/init/ 75 | 76 | The previous steps should have created the sagemath-patchbot image from the 77 | latest develop branch of Sage. Copy the file `upstart/containers` to 78 | `/etc/docker`. This contains configuration (read by the docker-manager 79 | service) for specific containers to create and run as services: 80 | 81 | sudo cp upstart/containers /etc/docker 82 | 83 | Then start the service either by rebooting or simply running: 84 | 85 | sudo service docker-manager start 86 | 87 | If there are any problems (e.g. the container doesn't appear to be running 88 | in `docker ps`) you can try restarting the `docker-manager` service, or the 89 | service *specific* to the sagemath-patchbot instance with: 90 | 91 | sudo service docker-instance NAME=sagemath-patchbot restart 92 | 93 | You can also take a look at the log for the service in: 94 | 95 | /var/log/upstart/docker-instance-sagemath-patchbot.log 96 | 97 | ## TODO 98 | 99 | - Replace all of the above documentation with some Ansible playbooks. 100 | -------------------------------------------------------------------------------- /infrastructure/upstart/containers: -------------------------------------------------------------------------------- 1 | sagemath-patchbot: --hostname sagemath-patchbot-docker sagemath/sagemath-patchbot 2 | -------------------------------------------------------------------------------- /infrastructure/upstart/docker-instance.conf: -------------------------------------------------------------------------------- 1 | description "Docker Container" 2 | 3 | stop on stopping docker 4 | # Docker has a timeout of 10 seconds so as long as this 5 | # is longer so we don't kill the wait process 6 | kill timeout 20 7 | 8 | # We don't want to TERM the `docker wait` process so we fake the signal 9 | # we send to it. The pre-stop script issues the `docker stop` command 10 | # which causes the `docker wait` process to exit 11 | kill signal CONT 12 | 13 | # Due to a bug in upstart we need to set the modes we consider 14 | # successful exists https://bugs.launchpad.net/upstart/+bug/568288 15 | normal exit 0 CONT 16 | 17 | respawn 18 | respawn limit 10 60 19 | 20 | instance ${NAME} 21 | 22 | pre-start script 23 | [ ! -f /etc/docker/containers ] && { stop; exit 0; } 24 | 25 | if ! grep -q "^${NAME}:" /etc/docker/containers; then 26 | stop 27 | exit 0 28 | fi 29 | end script 30 | 31 | script 32 | LINE=$(grep "^${NAME}:" /etc/docker/containers | cut -d: -f2-| sed 's/^\s*//') 33 | 34 | [ -f "/var/run/docker/${NAME}.cid" ] && { ID="$(cat /var/run/docker/${NAME}.cid)"; } 35 | 36 | START=1 37 | if [ ! -z "${ID}" ]; then 38 | if docker ps | grep -q "${ID}"; then 39 | START=0 40 | else 41 | NID=$(docker start ${ID} || true) 42 | [ "${NID}" = "${ID}" ] && START=0 43 | fi 44 | fi 45 | 46 | if [ $START -ne 0 ]; then 47 | ID=$(docker run -d ${LINE}) 48 | # After a brief wait, ensure that the container is running 49 | sleep 1 50 | if [ "$(docker inspect -f {{.State.Running}} $ID)" = "false" ]; then 51 | EXIT_CODE=$(docker inspect -f {{.State.ExitCode}} $ID) 52 | echo "Running ${NAME} failed with exit code ${EXIT_CODE}" 53 | exit $EXIT_CODE 54 | fi 55 | echo ${ID} > /var/run/docker/${NAME}.cid 56 | fi 57 | 58 | exec docker wait ${ID} 59 | end script 60 | 61 | pre-stop script 62 | [ -f "/var/run/docker/${NAME}.cid" ] && { ID="$(cat /var/run/docker/${NAME}.cid)"; } 63 | if [ ! -z "${ID}" ]; then 64 | docker stop "${ID}" || true 65 | fi 66 | end script 67 | -------------------------------------------------------------------------------- /infrastructure/upstart/docker-manager.conf: -------------------------------------------------------------------------------- 1 | description "Manage Docker Containers" 2 | 3 | start on started docker 4 | stop on stopping docker 5 | 6 | respawn 7 | 8 | pre-start script 9 | # Directory to store run data 10 | [ ! -d /var/run/docker ] && mkdir -p /var/run/docker 11 | 12 | # Directory to store config 13 | [ ! -d /etc/docker ] && mkdir -p /etc/docker 14 | 15 | [ ! -f /etc/docker/containers ] && { stop; exit 0; } 16 | 17 | while read line; do 18 | NAME=$(echo "$line" | cut -d: -f 1) 19 | start docker-instance NAME="$NAME" 20 | done < /etc/docker/containers 21 | end script 22 | 23 | post-stop script 24 | for inst in `initctl list | grep "^docker-instance "|awk '{print $2}'|tr -d ')'|tr -d '('` 25 | do 26 | stop docker-instance NAME=$inst 27 | done 28 | end script 29 | -------------------------------------------------------------------------------- /sagemath-base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | MAINTAINER Erik M. Bray 4 | 5 | RUN apt-get update -qq \ 6 | && apt-get install -y wget build-essential gfortran automake m4 dpkg-dev sudo python libssl-dev git \ 7 | && apt-get clean \ 8 | && rm -rf /var/lib/apt/lists/* 9 | 10 | # We *have* to add a non-root user since sage cannot be built as root 11 | # However, we do allow the 'sage' user to use sudo without a password 12 | RUN adduser --quiet --shell /bin/bash --gecos "Sage user,101,," --disabled-password sage \ 13 | && chown -R sage:sage /home/sage/ \ 14 | && echo "sage ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/01-sage \ 15 | && chmod 0440 /etc/sudoers.d/01-sage 16 | 17 | ENV SHELL /bin/bash 18 | 19 | # The unicode sage banner crashes Docker :( 20 | # see https://github.com/docker/docker/issues/21323 21 | # The "bare" banner is ASCII only 22 | ENV SAGE_BANNER bare 23 | 24 | EXPOSE 8080 25 | USER sage 26 | -------------------------------------------------------------------------------- /sagemath-develop: -------------------------------------------------------------------------------- 1 | sagemath -------------------------------------------------------------------------------- /sagemath-jupyter/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sagemath/sagemath 2 | 3 | MAINTAINER Erik M. Bray 4 | 5 | ARG SAGE_BRANCH=master 6 | EXPOSE 8888 7 | 8 | ENTRYPOINT sage -n jupyter --no-browser --ip=$(grep `hostname` /etc/hosts | cut -f1) --port=8888 9 | -------------------------------------------------------------------------------- /sagemath-local-develop/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sagemath/sagemath-base 2 | USER root 3 | # Allow 'sage' user to use sudo without a password 4 | RUN echo "sage ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers 5 | WORKDIR /src/sage 6 | RUN chown -R sage:sage /src/sage 7 | USER sage 8 | CMD [ "./sage", "-sh" ] 9 | -------------------------------------------------------------------------------- /sagemath-patchbot/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sagemath/sagemath-develop 2 | MAINTAINER Erik M. Bray 3 | 4 | ARG SAGE_BRANCH=develop 5 | # Not used, but included for compatibility with the sagemath-develop 6 | # Dockerfile 7 | ARG SAGE_COMMIT 8 | 9 | ARG PATCHBOT_URL=https://github.com/sagemath/sage-patchbot.git 10 | ARG PATCHBOT_REF=master 11 | 12 | USER root 13 | 14 | ENV DEBIAN_FRONTEND=noninteractive 15 | RUN apt-get update -qq \ 16 | && apt-get install -y python-pip jo \ 17 | && apt-get clean && rm -rf /var/lib/apt/lists/* 18 | 19 | RUN pip install git+$PATCHBOT_URL@$PATCHBOT_REF 20 | 21 | USER sage 22 | 23 | # Run through the entire test suite once so as to produce an initial test 24 | # timings log. This should at least reduce the incidence of non-deterministic 25 | # test failures. Ignore any test failures for now. 26 | RUN sage -t -a -p 0 --long; exit 0 27 | 28 | ARG N_CORES=1 29 | # Write a config file specifying the number of cores to use for the build 30 | # (by default taken from the N_CORES on the image build machine itself) along 31 | # with some other default config. 32 | RUN jo -p sage_root=$(sage --root) parallelism=$N_CORES retries=2 \ 33 | safe_only=false \ 34 | plugins=$(jo -a pyflakes) > patchbot.conf 35 | 36 | # By default, the patchbot starts by setting up a couple things and 37 | # running all the tests once to check that the base installation is 38 | # correct. Here we make sure to do this base check only once, at 39 | # construction time (see --count=0 and --skip-base). 40 | RUN patchbot --count=0 --config=patchbot.conf 41 | 42 | ENTRYPOINT patchbot --skip-base --config=patchbot.conf 43 | -------------------------------------------------------------------------------- /sagemath/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sagemath/sagemath-base 2 | 3 | MAINTAINER Erik M. Bray 4 | 5 | ARG SAGE_SRC_TARGET=/opt 6 | # Note: SAGE_BRANCH may also be a tag name 7 | # Note: SAGE_COMMIT should be the sha1 hash of the actual commit we're 8 | # building from--by passing in different values for this argument we 9 | # can invalidate Docker's cache for this image (currently there is a slight 10 | # race condition between this and the install_sage.sh script, but it is not 11 | # terribly important for the purpose of cache invalidation) 12 | ARG SAGE_BRANCH=master 13 | ARG SAGE_COMMIT=HEAD 14 | ARG N_CORES 15 | 16 | USER root 17 | COPY scripts/install_sage.sh /tmp/ 18 | # We do a few things as root in the sage install scripts, though the sage build 19 | # itself is done by sudo-ing as the sage user 20 | # make source checkout target, then run the install script 21 | # see https://github.com/docker/docker/issues/9547 for the sync 22 | RUN echo "Building Sage from $SAGE_BRANCH ($SAGE_COMMIT)" \ 23 | && mkdir -p $SAGE_SRC_TARGET \ 24 | && /tmp/install_sage.sh $SAGE_SRC_TARGET $SAGE_BRANCH \ 25 | && sync 26 | 27 | USER sage 28 | ENV HOME /home/sage 29 | WORKDIR /home/sage 30 | COPY scripts/post_install_sage.sh /tmp/ 31 | RUN /tmp/post_install_sage.sh $SAGE_SRC_TARGET && sudo rm -rf /tmp/* && sync 32 | 33 | ENTRYPOINT [ "sage-entrypoint" ] 34 | CMD [ "sage" ] 35 | -------------------------------------------------------------------------------- /sagemath/scripts/install_sage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # !!!NOTE!!! This script is intended to be run with root privileges 3 | # It will run as the 'sage' user when the time is right. 4 | SAGE_SRC_TARGET=${1%/} 5 | BRANCH=$2 6 | 7 | if [ -z $SAGE_SRC_TARGET ]; then 8 | >&2 echo "Must specify a target directory for the sage source checkout" 9 | exit 1 10 | fi 11 | 12 | if [ -z $BRANCH ]; then 13 | >&2 echo "Must specify a branch to build" 14 | exit 1 15 | fi 16 | 17 | N_CORES=$(cat /proc/cpuinfo | grep processor | wc -l) 18 | 19 | export SAGE_FAT_BINARY="yes" 20 | # Just to be sure Sage doesn't try to build its own GCC (even though 21 | # it shouldn't with a recent GCC package from the system and with gfortran) 22 | export SAGE_INSTALL_GCC="no" 23 | export MAKE="make -j${N_CORES}" 24 | cd "$SAGE_SRC_TARGET" 25 | git clone --depth 1 --branch ${BRANCH} git://git.sagemath.org/sage.git 26 | chown -R sage:sage sage 27 | cd sage 28 | 29 | # Sage can't be built as root, for reasons... 30 | # Here -E inherits the environment from root, however it's important to 31 | # include -H to set HOME=/home/sage, otherwise DOT_SAGE will not be set 32 | # correctly and the build will fail! 33 | sudo -H -E -u sage make || exit 1 34 | 35 | # Add aliases for sage and sagemath 36 | ln -sf "${SAGE_SRC_TARGET}/sage/sage" /usr/bin/sage 37 | ln -sf "${SAGE_SRC_TARGET}/sage/sage" /usr/bin/sagemath 38 | 39 | # Clean up artifacts from the sage build that we don't need for runtime or 40 | # running the tests 41 | # 42 | # Unfortunately none of the existing make targets for sage cover this ground 43 | # exactly 44 | 45 | # For the 'develop' image we leave everything as it would be after a 46 | # successful sage build 47 | if [ $BRANCH != "develop" ]; then 48 | make misc-clean 49 | make -C src/ clean 50 | 51 | rm -rf upstream/ 52 | rm -rf src/doc/output/doctrees/ 53 | rm -rf .git 54 | 55 | # Strip binaries 56 | LC_ALL=C find local/lib local/bin -type f -exec strip '{}' ';' 2>&1 | grep -v "File format not recognized" | grep -v "File truncated" || true 57 | fi 58 | -------------------------------------------------------------------------------- /sagemath/scripts/post_install_sage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Additional setup to perform after building and installing Sage 3 | # This is broken out into a separate script so it can be run as 4 | # a separate step in the Dockerfile without performing a full 5 | # rebuild. This script is run as the 'sage' user. 6 | 7 | SAGE_SRC_TARGET=${1%/} 8 | if [ -z $SAGE_SRC_TARGET ]; then 9 | >&2 echo "Must specify a target directory for the sage source checkout" 10 | exit 1 11 | fi 12 | 13 | # Put scripts to start gap, gp, maxima, ... in /usr/bin 14 | sudo sage --nodotsage -c "install_scripts('/usr/bin')" 15 | 16 | # Setup the admin password for Sage's lecacy notebook to avoid need for later 17 | # user interaction 18 | # This should also be run as the 'sage' user to ensure that the resulting 19 | # configuration is written to their DOT_SAGE 20 | sage < /tmp/orig_env.txt 45 | sage -sh -c set | sort > /tmp/sage_env.txt 46 | envvars=$(diff /tmp/orig_env.txt /tmp/sage_env.txt | grep '^> ' | grep -v '^SHLVL=\|^_=' | cut -d' ' -f2-) 47 | envvars=$(echo "$envvars" | sed 's/^/export /') 48 | cat > "$SAGE_SRC_TARGET/sage/local/bin/sage-entrypoint.sh" <<_EOF_ 49 | #!/bin/bash 50 | ${envvars} 51 | exec "\$@" 52 | _EOF_ 53 | chmod +x "$SAGE_SRC_TARGET/sage/local/bin/sage-entrypoint.sh" 54 | rm -f /tmp/*_env.txt 55 | sudo ln -s "$SAGE_SRC_TARGET/sage/local/bin/sage-entrypoint.sh" /usr/local/bin/sage-entrypoint 56 | --------------------------------------------------------------------------------