Skip to content

Commit

Permalink
Merge pull request #266 from davidycliao/0.1.7
Browse files Browse the repository at this point in the history
0.1.7
  • Loading branch information
davidycliao authored Jan 5, 2025
2 parents e602c4e + 2fa2c98 commit 2aa9786
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 97 deletions.
47 changes: 39 additions & 8 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
branches: [main, master]
pull_request:
branches: [main, master]


jobs:
R-CMD-check:
runs-on: ubuntu-latest
Expand All @@ -17,49 +19,78 @@ jobs:
with:
use-public-rspm: true
- uses: r-lib/actions/setup-pandoc@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install flair
- name: Install R dependencies
run: |
install.packages('remotes')
remotes::install_github("davidycliao/flaiR", force = TRUE)
shell: Rscript {0}

- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: rcmdcheck


docker:
needs: R-CMD-check
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v3
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
buildkitd-flags: --debug

- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/${{ github.repository_owner }}/flair-rstudio
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push RStudio image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/flair-rstudio:latest
labels: |
org.opencontainers.image.title=flaiR-RStudio
org.opencontainers.image.version=0.0.7
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
DEFAULT_USER=rstudio
secrets: |
PASSWORD=${{ secrets.RSTUDIO_PASSWORD }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
82 changes: 40 additions & 42 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,69 +1,67 @@
FROM rocker/r-ver:latest

# 系統更新和安裝安全性修補
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
# Install system dependencies
RUN apt-get update && apt-get install -y \
python3-minimal \
python3-pip \
python3-venv \
python3-full \
libcurl4-openssl-dev \
libssl-dev \
gdebi-core \
wget \
sudo && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
sudo \
curl

# 安裝 RStudio Server
RUN wget --progress=dot:giga https://download2.rstudio.org/server/jammy/amd64/rstudio-server-2023.12.1-402-amd64.deb && \
# Create rstudio user
ENV USER=rstudio
ENV PASSWORD=rstudio123
RUN useradd -m $USER && \
echo "$USER:$PASSWORD" | chpasswd && \
adduser $USER sudo && \
echo "$USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# Install RStudio Server
RUN wget https://download2.rstudio.org/server/jammy/amd64/rstudio-server-2023.12.1-402-amd64.deb && \
gdebi -n rstudio-server-2023.12.1-402-amd64.deb && \
rm rstudio-server-*.deb

# Python 虛擬環境設置
RUN python3 -m venv /opt/venv
# Create and configure Python virtual environment
RUN python3 -m venv /opt/venv && \
chown -R $USER:$USER /opt/venv

ENV PATH="/opt/venv/bin:$PATH"
ENV RETICULATE_PYTHON="/opt/venv/bin/python"

# Setup R environment config
RUN mkdir -p /usr/local/lib/R/etc && \
echo "RETICULATE_PYTHON=/opt/venv/bin/python" >> /usr/local/lib/R/etc/Renviron.site && \
chown -R $USER:$USER /usr/local/lib/R/etc/Renviron.site && \
chmod 644 /usr/local/lib/R/etc/Renviron.site

# R env
RUN echo "RETICULATE_PYTHON=/opt/venv/bin/python" >> /usr/local/lib/R/etc/Renviron.site

# 安裝更新的 Python 包
RUN /opt/venv/bin/pip install --no-cache-dir --upgrade pip && \
/opt/venv/bin/pip install --no-cache-dir \
numpy>=1.26.4 \
scipy>=1.12.0 \
# Install Python packages
RUN /opt/venv/bin/pip install --no-cache-dir \
numpy==1.26.4 \
scipy==1.12.0 \
transformers \
torch \
flair

# 安裝 R 包
RUN install2.r --error --deps TRUE \
reticulate \
remotes && \
# Install R packages
RUN R -e "install.packages('reticulate', repos='https://cloud.r-project.org/', dependencies=TRUE)" && \
R -e "install.packages('remotes', repos='https://cloud.r-project.org/', dependencies=TRUE)" && \
R -e "remotes::install_github('davidycliao/flaiR', dependencies=TRUE)"

# 使用者設置(使用 ARG 而不是 ENV 來處理敏感資訊)
ARG USER=rstudio
ARG PASSWORD=rstudio123
RUN useradd -m $USER && \
echo "$USER:$PASSWORD" | chpasswd && \
adduser $USER sudo
# Set working directory
WORKDIR /home/$USER
RUN chown -R $USER:$USER /home/$USER

# Add healthcheck
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8787/ || exit 1

# 設置權限
RUN mkdir -p /home/$USER && \
chown -R $USER:$USER /home/$USER && \
chown -R $USER:$USER /opt/venv && \
chown -R $USER:$USER /usr/local/lib/R/etc/Renviron.site && \
chmod 644 /usr/local/lib/R/etc/Renviron.site

# 清理
RUN apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Expose port
EXPOSE 8787

# Run service as rstudio user
USER $USER
CMD ["/usr/lib/rstudio-server/bin/rserver", "--server-daemonize=0"]

121 changes: 74 additions & 47 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,86 +89,113 @@
# }
# }
.onAttach <- function(...) {
# Check if running in Docker
Sys.unsetenv("RETICULATE_PYTHON")
# Docker 環境檢查及 Python 設置
in_docker <- file.exists("/.dockerenv")

# Determine Python command
if (in_docker) {
python_path <- "/opt/venv/bin/python"
# Docker 環境使用固定路徑
python_path <- "/opt/venv/bin/python3"
Sys.setenv(RETICULATE_PYTHON = python_path)
} else {
# 非 Docker 環境
python_cmd <- if (Sys.info()["sysname"] == "Windows") "python" else "python3"
python_path <- Sys.which(python_cmd)
}

# Check Python path
# 檢查 Python 路徑
if (python_path == "") {
packageStartupMessage("Cannot locate Python executable. Ensure it's installed and in your system's PATH. flaiR functionality requiring Python will not be available.")
packageStartupMessage("Cannot locate Python executable. Ensure Python is installed and in PATH.")
return(invisible(NULL))
}

# Check Python version
# 檢查 Python 版本
tryCatch({
python_version <- system(paste(python_path, "--version"), intern = TRUE)
if (!grepl("Python 3", python_version)) {
packageStartupMessage("Python 3 is required. flaiR functionality requiring Python will not be available.")
python_version <- system2(python_path, "--version", stdout = TRUE, stderr = TRUE)
if (!any(grepl("Python 3", python_version))) {
packageStartupMessage("Python 3 is required.")
return(invisible(NULL))
}
}, error = function(e) {
packageStartupMessage(paste("Failed to get Python version. Error:", e$message))
packageStartupMessage(sprintf("Failed to check Python version: %s", e$message))
return(invisible(NULL))
})

# Version check functions
# 檢查 PyTorch 版本
check_torch_version <- function() {
torch_version_command <- paste(python_path, "-c \"import torch; print(torch.__version__)\"")
result <- system(torch_version_command, intern = TRUE)
if (length(result) == 0 || result[1] == "ERROR" || is.na(result[1])) {
return(list(paste("PyTorch", paste0("\033[31m", "\u2717", "\033[39m"), sep = " "), FALSE))
}
return(list(paste("PyTorch", paste0("\033[32m", "\u2713", "\033[39m"), result[1], sep = " "), TRUE, result[1]))
tryCatch({
cmd <- sprintf("%s -c 'import torch; print(torch.__version__)'", python_path)
result <- system(cmd, intern = TRUE)
if (length(result) > 0 && !is.na(result[1])) {
return(list(
status = paste("PyTorch", "\u2713", result[1]),
success = TRUE,
version = result[1]
))
}
}, error = function(e) NULL)
return(list(status = paste("PyTorch", "\u2717"), success = FALSE))
}

# 檢查 Flair 版本
check_flair_version <- function() {
flair_version_command <- paste(python_path, "-c \"import flair; print(flair.__version__)\"")
result <- system(flair_version_command, intern = TRUE)
if (length(result) == 0 || result[1] == "ERROR" || is.na(result[1])) {
return(list(paste("flair", paste0("\033[31m", "\u2717", "\033[39m"), sep = " "), FALSE))
}
return(list(paste("flair", paste0("\033[32m", "\u2713", "\033[39m"), result[1], sep = " "), TRUE, result[1]))
tryCatch({
cmd <- sprintf("%s -c 'import flair; print(flair.__version__)'", python_path)
result <- system(cmd, intern = TRUE)
if (length(result) > 0 && !is.na(result[1])) {
return(list(
status = paste("Flair", "\u2713", result[1]),
success = TRUE,
version = result[1]
))
}
}, error = function(e) NULL)
return(list(status = paste("Flair", "\u2717"), success = FALSE))
}

flair_version <- check_flair_version()
torch_version <- check_torch_version()
# 執行版本檢查
flair_check <- check_flair_version()
torch_check <- check_torch_version()

if (isFALSE(flair_version[[2]])) {
packageStartupMessage(sprintf(" Flair %-50s", paste0("is installing from Python")))
# 如果 Flair 未安裝,嘗試安裝
if (!flair_check$success) {
packageStartupMessage("Installing Flair and dependencies...")

# Docker-specific installation commands
if (in_docker) {
commands <- c(
paste(python_path, "-m pip install --no-cache-dir numpy==1.26.4"),
paste(python_path, "-m pip install --no-cache-dir torch"),
paste(python_path, "-m pip install --no-cache-dir flair"),
paste(python_path, "-m pip install --no-cache-dir scipy==1.12.0")
# 安裝命令
install_commands <- if (in_docker) {
c(
sprintf("%s -m pip install --no-cache-dir numpy==1.26.4", python_path),
sprintf("%s -m pip install --no-cache-dir torch", python_path),
sprintf("%s -m pip install --no-cache-dir flair", python_path),
sprintf("%s -m pip install --no-cache-dir scipy==1.12.0", python_path)
)
} else {
commands <- c(
paste(python_path, "-m pip install --upgrade pip"),
paste(python_path, "-m pip install torch"),
paste(python_path, "-m pip install flair"),
paste(python_path, "-m pip install scipy==1.12.0")
c(
sprintf("%s -m pip install --upgrade pip", python_path),
sprintf("%s -m pip install torch", python_path),
sprintf("%s -m pip install flair", python_path),
sprintf("%s -m pip install scipy==1.12.0", python_path)
)
}

command_statuses <- vapply(commands, system, FUN.VALUE = integer(1))
# 執行安裝
install_status <- vapply(install_commands, function(cmd) {
tryCatch({
system(cmd)
TRUE
}, error = function(e) FALSE)
}, logical(1))

flair_check_again <- check_flair_version()
if (isFALSE(flair_check_again[[2]])) {
packageStartupMessage("Failed to install Flair. {flaiR} requires Flair NLP. Please ensure Flair NLP is installed in Python manually.")
# 重新檢查安裝
flair_check <- check_flair_version()
if (!flair_check$success) {
packageStartupMessage("Failed to install Flair. Please install manually.")
return(invisible(NULL))
}
} else {
packageStartupMessage(sprintf("\033[1m\033[34mflaiR\033[39m\033[22m: \033[1m\033[33mAn R Wrapper for Accessing Flair NLP\033[39m\033[22m %-5s",
paste("\033[1m\033[33m", flair_version[[3]], "\033[39m\033[22m", sep = "")))
}

# 顯示啟動訊息
packageStartupMessage(sprintf(
"flaiR: An R Wrapper for Accessing Flair NLP %s",
if (flair_check$success) flair_check$version else ""
))
}

0 comments on commit 2aa9786

Please sign in to comment.