Skip to content

Commit

Permalink
Merge pull request #68 from luclaurent/devel-docker
Browse files Browse the repository at this point in the history
Create docker container for amc2moodle.
  • Loading branch information
nennigb authored Apr 15, 2022
2 parents 23e8e44 + 029cdfe commit 0745671
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 0 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/build-container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: 'Build amc2moodle container'

on:
push:
# branches:
# - 'master'
tags:
- 'v*'


jobs:
build:
name: 'Build amc2moodle container'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- id: docker-tag
uses: yuya-takeyama/docker-tag-from-github-ref-action@v1
with:
latest-branches: 'main,master'
- name: "Build:checkout"
uses: actions/checkout@v2
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Login to Github Packages
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.PAT }}
- name: 'Build:dockerimage'
uses: docker/build-push-action@v2
with:
# relative path to the place where source code with Dockerfile is located
context: ./docker
tags: ghcr.io/${{ github.repository_owner }}/amc2moodle:${{ steps.docker-tag.outputs.tag }},ghcr.io/${{ github.repository_owner }}/amc2moodle:latest
push: true
cache-from: type=gha
cache-to: type=gha
# # build on feature branches, push only on main branch
# push: ${{ github.ref == 'refs/heads/main' }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Note that [auto-multiple-choice](https://www.auto-multiple-choice.net) (amc) LaT

## Installation

A Docker image with `amc2moodle` and its dependencies is available at [ghcr.io/nennigb/amc2moodle](ghcr.io/nennigb/amc2moodle).
Once the docker software is installed, this image allows to use `amc2moodle` on **windows plateforms** or to add the resource isolation features on linux or macOS. For more information, see the [`amc2moodle`' docker README](docker/README.md).

### Before installing amc2moodle:

- install python (version >=3.5)
Expand Down
55 changes: 55 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
FROM texlive/texlive:latest

# labels
LABEL AUTHOR='Luc Laurent'
LABEL MAINTAINER='Luc Laurent & Benoit Nennig'

# install debian packages
RUN apt update && \
apt install -yy wget ghostscript imagemagick libtext-unidecode-perl latexml xmlindent python3-pip git && \
apt clean

# move policy file
RUN mv /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xml.off

# install pip and Python pkgs
# RUN pip3 install -U pip && \
# pip install amc2moodle
WORKDIR /tmp
RUN git clone https://github.com/nennigb/amc2moodle.git -b master
WORKDIR /tmp/amc2moodle
RUN pip3 install .

# check if amc2moodle and moodle2amc work
WORKDIR /
RUN python -m amc2moodle.amc2moodle.test && \
python -m amc2moodle.utils.test

# create dir
RUN mkdir /tmp/work
RUN mkdir /tmp/daemon
VOLUME /tmp/work
VOLUME /tmp/daemon

# create new user
RUN groupadd -r user && useradd -r -g user user
RUN chown user:user /tmp/daemon
RUN chown user:user /tmp/work


USER user

#working dir
WORKDIR /tmp/work

#declare directory using environement
ENV MONITOR_DIR=/tmp/work
ENV LOG_DIR=/tmp/daemon

# copy autorun script for amc2moodle/moodle2amc
COPY autorun-amc2moodle.sh /tmp/.
#RUN ["/tmp/autorun-amc2moodle.sh",">","/dev/null","2>&1&"]

# execute script
ENTRYPOINT ["/tmp/autorun-amc2moodle.sh",">","/dev/null","2>&1&"]
# ENTRYPOINT ["tail","-f","/dev/null"]
87 changes: 87 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Docker's version of `amc2moodle`

A docker version of `amc2moodle` is available and it starts a daemon server to automatically execute `amc2moodle` or `moodle2amc`.

Alternatively, it is also possible to run an interactive shell in the docker to recover standard `amc2moodle` command line interface.

# Installation

The container can be downloaded using the following command
```
docker pull ghcr.io/nennigb/amc2moodle:latest
```

The container proposes to mount two volumes:
- `/tmp/work` (**mandatory mount**) that must be link to a specific folder on the host computer
- `/tmp/daemon` (optional mount) that store the log file of the daemon

For instance, the container can be run in CLI (in detached mode) with the following command:
```
docker run --name amc2moodle -d -v "DIRA:/tmp/work" -v "DIRB:/tmp/daemon" ghcr.io/nennigb/amc2moodle
```

NB: `DIRA` and `DIRB` must be absolute paths.

**it is recommended to use only empty folder with no critical contents for `DIRA` and `DIRB`.**

The container can be stopped using the following command
```
docker stop amc2moodle
```
# Usage as daemon/server (automatic building)

We assume that `DIRA` has been mounted and bound to `/tmp/work`.

Folder `DIRA` can be populated with every required data to run `amc2moodle` or `moodle2amc` such as
```
DIRA
├── ...
├── a_amc2moodle.tex
├── b_moodle2amc.xml
└── ...
```

The server will automatically detects the files and run the appropriate script:
- to run `amc2moodle` the main LaTeX file must be rename such as the end the name ends with `amc2moodle.tex` (such as the file `a_amc2moodle.tex`)
- to run `moodle2amc` the main LaTeX file must be rename such as the end the name ends with `moodle2amc.xml` (such as the file `b_moodle2amc.xml`)

After the run, the folder will contain additional files provided by the daemon/server and the script:

```
DIRA
├── ...
├── a_amc2moodle.tex
├── a_amc2moodle.tex.lock
├── a_amc2moodle_amc2moodle.log
├── b_moodle2amc.xml
├── b_moodle2amc.xml.lock
├── b_moodle2amc_moodle2amc.log
└── ...
```

Logfiles (`*.log`) are provided by the `amc2moodle`or `moodle2amc` scripts and allows to check if everything is fine.

Lockfiles (`*.lock`) are provided by the daemon/server. **Running a new execution could be obtain by removing one of this files.**

In addition, if the `DIRB` directory has been mounted, it will contain detailed logfiles of the daemon and could be use for debug.

# Advanced usage with command line

Since the container has been started with for instance the procedure given [above](#installation). A command line within the docker can be obtained by running the following command:
```
docker exec -it amc2moodle /bin/bash
```
With this shell, classical `amc2moodle` and `moodle2amc` commands are available (see [here](../README.md#conversion) for usable syntax).


NB:
- this command could be adapted depending on the name of the executed container.
- execution of the previous does not stop the server/daemon.
- the files should be visible from the docker i.e. in `DIRA` folder or in another given volume
- the command line interface could also be run without starting the `amc2moodle` daemon (`docker run` vs `docker exec`)


<!---
# Development
--->

84 changes: 84 additions & 0 deletions docker/autorun-amc2moodle.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash

## script to run amc2moodle or moodle2amc automatically in a specific folder

# monitored and daemon folder
MONITOR_DIR_DEF=/tmp/work
LOG_DIR_DEF=/tmp/daemon
#
if [ -z ${MONITOR_DIR+x} ]
then
MONITOR_DIR=${MONITOR_DIR_DEF}
fi
if [ -z ${LOG_DIR+x} ]
then
LOG_DIR=${LOG_DIR_DEF}
fi

# function to run amc2moodle
function run_amc2moodle()
{
amc2moodle -x --silent "$1"
touch "$1".lock
}

# function to run moodle2amc
function run_moodle2amc()
{
moodle2amc --silent "$1"
touch "$1".lock
}


#log manage
now=$(date +"%Y-%m-%d_%H-%M-%s")
mkdir -p ${LOG_DIR}
LOGFILE=${LOG_DIR}/${now}_autorun.log

{

printf "Start daemon\n\n"
printf "Log dir: ${LOG_DIR}\n"
printf "Monitored dir: ${MONITOR_DIR}\n"
# loop
while true
do
#execute on amc2moodle waiting files
files=$(ls *amc2moodle.tex 2> /dev/null)
nbfiles=$(ls *amc2moodle.tex 2> /dev/null | wc -l)
if [ "$nbfiles" != "0" ]
then
for file in ${files}
do
if [[ -f "${file}.lock" ]]
then
printf " >>> ${file}.lock exists\n"
else
printf " >>> Run amc2moodle on ${file}\n"
run_amc2moodle "${file}"
fi
done
fi

#execute on moodle2amc waiting files
files=$(ls *moodle2amc.xml 2> /dev/null)
nbfiles=$(ls *moodle2amc.xml 2> /dev/null | wc -l)
if [ "$nbfiles" != "0" ]
then
for file in ${files}
do
if [[ -f "${file}.lock" ]]
then
printf " >>> ${file}.lock exists\n"
else
printf " >>> Run moodle2amc on ${file}\n"
run_moodle2amc "${file}"
fi
done
fi
sleep 2
done
printf "Daemon stopped"


} 2>&1 | tee ${LOGFILE}

0 comments on commit 0745671

Please sign in to comment.