Commit 0f77ba13 authored by Jean-Francois Rey's avatar Jean-Francois Rey

add single user dockerfile

add docker compose and stack file
parent 2e9b7bbf
......@@ -23,7 +23,7 @@ buildImageDocker:
stage: build_img
script:
- docker pull $CI_REGISTRY_IMAGE:latest || true
- docker build --build-arg APP_NAME=$CI_PROJECT_NAME --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest -f Dockerfile .
- docker build --build-arg APP_NAME=$CI_PROJECT_NAME --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest -f Dockerfile.multi .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
after_script:
......@@ -75,3 +75,49 @@ deploy:
docker pull $CI_REGISTRY_IMAGE:latest;
docker logout $CI_REGISTRY_IMAGE;"
## Deploy as a service on a server
## specific runner
deploy-standalone:
tags:
- "myprodserver"
- "deploy"
- "prod"
image: docker:19.03
stage: deploy
only:
- master
when: manual
environment:
name: shiny.website.org
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker-compose up -d -f myApp-compose.yml
after_script:
- docker logout $CI_REGISTRY
## Deploy as a stack on a docker swarm server using a local registry
## specific runner
deploy-swarm:
tags:
- "myswarmprodserver"
- "deploy"
- "prod"
image: docker:19.03
stage: deploy
only:
- master
when: manual
environment:
name: shiny.website.org
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker pull $CI_REGISTRY_IMAGE/$CI_PROJECT_NAME:latest
- docker tag $CI_REGISTRY_IMAGE/$CI_PROJECT_NAME:latest 127.0.0.1:5000/$CI_PROJECT_NAME:latest
- docker push 127.0.0.1:5000/$CI_PROJECT_NAME:latest
- docker image rm $CI_REGISTRY_IMAGE/$CI_PROJECT_NAME:latest
- docker stack deploy -c myApp-stack.yml --with-registry-auth myApp-stack
after_script:
- docker logout $CI_REGISTRY
FROM r-base:latest
LABEL maintainer "Jean-Francois Rey <jean-francois.rey@inra.fr>"
## Add here libraries dependencies
## there are more libraries that are needed here
RUN apt-get update && apt-get install -y \
sudo \
gdebi-core \
pandoc \
pandoc-citeproc \
libcurl4-gnutls-dev \
libcairo2-dev/unstable \
libxt-dev \
libssl-dev \
libpq-dev \
libgeos-dev \
locales \
libproj-dev \
libgdal-dev gdal-bin \
libudunits2-0 libudunits2-data libudunits2-dev \
git \
openssh-client \
libssh2-1-dev \
libgit2-dev \
libglib2.0-dev/unstable \
libgsl-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
## Change timezone
ENV CONTAINER_TIMEZONE Europe/Paris
ENV TZ Europe/Paris
RUN sudo echo "Europe/Paris" > /etc/timezone
RUN echo "fr_FR.UTF-8 UTF-8" >> /etc/locale.gen \
&& locale-gen fr_FR.UTF8 \
&& /usr/sbin/update-locale LANG=fr_FR.UTF-8
ENV LC_ALL fr_FR.UTF-8
ENV LANG fr_FR.UTF-8
## R package dependencies
## Add here R packages dependencies
RUN Rscript -e "install.packages(c('shiny'), repos='https://cran.biotools.fr/')"
## To get last version of packages
# comment it if you install specific R packages version
RUN Rscript -e "update.packages(ask=FALSE)"
## App name by default, the name is set at docker build dynamically using project name
ARG APP_NAME="superApp"
## Clean unnecessary libraries
RUN apt-get update && apt-get remove --purge -y \
gdebi-core \
libcurl4-gnutls-dev \
libcairo2-dev/unstable \
libxt-dev \
libssl-dev \
libpq-dev \
libgeos-dev \
libproj-dev \
libgdal-dev \
libudunits2-dev \
git \
openssh-client \
libssh2-1-dev \
libgit2-dev \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
## Change shiny user rights
## USER shiny
RUN passwd shiny -d
WORKDIR /home/shiny
## Copy the application into image
## Add here files and directory necessary for the app.
## global.R ui.R server.R ...
RUN mkdir -p /home/shiny//${APP_NAME}
COPY ui.R /home/shiny/${APP_NAME}
COPY server.R /home/shiny/${APP_NAME}
#COPY global.R /home/shiny/${APP_NAME}
COPY www/* /home/shiny/${APP_NAME}/www/
# Copy App directory
#COPY myApp /home/shiny/${APP_NAME}
USER shiny
EXPOSE 3838
CMD ["Rscript","-e","shiny::runApp('/home/shiny/${APP_NAME}', port = 3838)"]
......@@ -5,7 +5,7 @@
This project hosts the repository of a Cookbook to create Docker image of a R Shiny
App and to deploy it in production.
This template builds a Docker image of the R Shiny App using the __Dockerfile__
This template builds a Docker image of the R Shiny App using a __Dockerfile__
and deploys it to a server. All tasks (jobs) are set in the __.gitlab-ci.yml__ file.
**Table of Contents**
......@@ -17,7 +17,7 @@ and deploys it to a server. All tasks (jobs) are set in the __.gitlab-ci.yml__ f
- [The Project](#the-project-repository)
- [The Runners](#the-runners)
- [The .gitlab-ci.yml file](#the-gitlab-ciyml-file)
- [Dockerfile](#dockerfile)
- [Dockerfiles](#dockerfiles)
- [Test the docker image](#test-the-docker-image)
- [Author](#author)
- [License](#license)
......@@ -38,8 +38,10 @@ and deploys it to a server. All tasks (jobs) are set in the __.gitlab-ci.yml__ f
* __[ui.R](ui.R)__, __[server.R](server.R)__ and __[www/](www)__ : R Shiny App files and directory
* __[.gitlab-ci.yml](.gitlab-ci.yml)__ : file configuring the CI/CD pipeline
* __[Dockerfile](Dockerfile)__ : file to build a Docker image of the App
* __[Dockerfile.multi](Dockerfile.multi)__ : file to build a Docker image of the App with shiny server (multi-users)
* __[Dockerfile.single](Dockerfile.single)__ : file to build a Docker image of the App (single-user)
* __[LICENSE](LICENSE)__ : the license file
* __[[myApp-compose.yml]]__ and __[myApp-stack.yml]]__ : specific deployment files for docker.
## Principle
......@@ -47,7 +49,7 @@ and deploys it to a server. All tasks (jobs) are set in the __.gitlab-ci.yml__ f
* At push, in GitLab repository, the pipeline is trigger.
* GitLab use __[.gitlab-ci.yml](.gitlab-ci.yml)__ file to set the pipeline and run it on runners.
* First it builds the docker image using __[Dockerfile](Dockerfile)__
* First it builds the docker image using __[Dockerfile](Dockerfile.multi)__
* Then it pushs it in the container registry of the project (with commit ID and _latest_ tags)
* At the end it deploys the image in a server (with a docker environment)
......@@ -60,17 +62,17 @@ You can fork this project and use it as a template.
* Files in the project:
* __[ui.R](ui.R)__, __[server.R](server.R)__ and __[www/](www)__ : R Shiny App files and directory
* __[.gitlab-ci.yml](.gitlab-ci.yml)__ : file configuring the CI/CD pipeline
* __[Dockerfile](Dockerfile)__ : file to build a Docker image of the App
* __[Dockerfile](Dockerfile.multi)__ : file to build a Docker image of the App
You need to enable __Pipelines__ in the project setting (_Setting -> General -> Visibility_)
and enable __Shared Runners__ and the _dind_ __Specific Runners__ (see below).
You need to set secret variables (Setting -> CI/CD -> Variables) to allow deployment :
You need to set secret variables (Setting -> CI/CD -> Variables) to allowi default deployment :
* __DEPLOY\_USER__ : user ID
* __DEPLOY\_PWD__ : user password
* __DEPLOY\_IP__ : the server IP to deploy to
You need to enable __Container registry__ in project setting (_Setting -> General -> Visibility_).
The __.gitlab-ci.yml__ file no need to be modify.
The __.gitlab-ci.yml__ file no need to be modify (just comment deploy parts that is not needed).
### The Runners
......@@ -82,25 +84,36 @@ Two types of Runners is needed:
Here you have to set your runners or ask GitLab administrator to set them.
In _Setting -> CI/CD -> Runners_ enable __Shared Runners__ and __Specific Runners__ tag as (dind).
> For standalone and docker-swarm deployment you need to use a specify runner that mount docker host sockets.
## The .gitlab-ci.yml file
__[.gitlab-ci.yml](.gitlab-ci.yml)__ is the configuration file for the CI/CD pipeline. There are three jobs :
* __buildImageDocker__ : It builds a docker image of the R Shiny App using the __[Dockerfile](dockerfile)__ and
* __buildImageDocker__ : It builds a docker image of the R Shiny App using the __[Dockerfile](Dockerfile.multi)__ and
records it to the container registry of the project.
* __retag__ : a fast way to rollback, it retags to _latest_ a commit.
* __deploy__ : pull the image (tag as _latest_) from the project container registry to a server
(set in secret variables).
This file can be use as it. But you may want to change the server URL in the __deploy__ job.
This file can be use as it. But you have to comment the __deploy__ part that you do not need and you may change the server URL too.
## Dockerfile
### Deployement strategies
__[Dockerfile](Dockerfile)__ is the file use to build the docker image.
There is three deployments strategies in the __.gitlab-ci.yml__ file, you may use just one:
* __deploy__ : Pull the docker image on a server using secrets credentials.
* __deploy-standalone__: use docker-compose (and [myApp-compose.yml](myApp-compose.yml) ) to create a service (using a specific runner)
* __deploy-swarm__: use docker stack (and [myApp-stack.yml](myApp-stack.yml) to create a stack on a docker swarm cluster using a specific runner. And use traefik V2 as frontal LB in options.
## Dockerfiles
__[Dockerfile.multi](Dockerfile.multi)__ is the file use to build the docker image for __multi-users__.
It describes how to create a docker image containing system libraries dependences,
a R Shiny Server, R packages dependencies, files (and directories) of the R Shiny App
and some configurations files.
__[Dockerfile.single](Dockerfile.single)__ is the file use to build the docker image for __single-user__.
It describes how to create a docker image containing system libraries dependences,
R packages dependencies, files (and directories) of the R Shiny App and some configurations files.
## Test the docker image
......
version: '3.7'
services:
myApp_public:
image: gitlab.paca.inrae.fr:4567/r-shiny-app-ci-cd:latest
container_name: myAwesomeApp
ports :
- "80:3838"
restart_policy:
condition: on-failure
volumes:
- /var/log/shiny:/var/log/shiny-server
version: '3.7'
services:
myApp_public:
image: 127.0.0.1:5000/r-shiny-app-ci-cd:latest
deploy:
mode: global
#resources:
# limits:
# cpus: "0.5"
# memory: 1G
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-public"
- "traefik.docker.lbswarm=false"
- "traefik.http.services.myapp.loadbalancer.server.port=3838"
- "traefik.http.services.myapp.loadbalancer.passhostheader=true"
- "traefik.http.services.myapp.loadbalancer.sticky=true"
- "traefik.http.services.myapp.loadbalancer.sticky.cookie.httponly=true"
- "traefik.http.routers.myapp.rule=Host(`shiny.website.org`)"
- "traefik.http.routers.myapp.entrypoints=web"
#- "traefik.http.routers.myapp_tls.rule=Host(`shiny.website.org`)"
#- "traefik.http.routers.myapp_tls.entrypoints=websecure"
#- "traefik.http.routers.myapp_tls.tls=true"
volumes:
- /var/log/shiny:/var/log/shiny-server
networks:
- traefik-public
networks:
traefik-public:
external: true
name: traefik-public
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment