# 构建镜像: Rstudio + R4.1.0 + Seurat 4.0.5
> Create on 2021/10/25 by [Dawneve](https://github.com/dawneve)
| [Biomooc](//www.biomooc.com) / [Docker](/linux/docker-tutorial.html)
---
镜像信息:
- 构建的镜像是 R4.1.0 + Rstudio server + Seurat 4.0.5; 默认用户 rstudio,带sudo权限。
- 想直接使用镜像的,请看第3: `$ docker pull dawneve/seurat:4.0.5r1`
---
有3个方案:
- 全新镜像,安装 R, Rstudio, Seurat;
- Rstudio 基础镜像,安装 Seurat;
- Seurat 基础镜像,安装Rstudio;
方案1太繁琐了,另外两个方案各有优劣。本文选择第三个,因为它只需要安装Rstudio即可使用。
---
前提准备:
```
# 要先安装好最新版的 docker。
$ docker --version
Docker version 20.10.9, build c2ea9bc
# 本文示例宿主机是 CentOS 7.9。使用普通用户,在 docker 组。
```
## 1. 拉取基础镜像、安装文件
(1) 空镜像(可选)
$ docker pull ubuntu:20.04
(2) Rstudio 基础镜像(可选)
[Rstudio 专栏](https://environments.rstudio.com/docker) 提到 **Rocker Project**:
The Rocker project is a community driven effort to create a series of self-contained images for R development. These images can often be used as “virtual machines”. The image labels define their contents, e.g. the rocker/tidyverse image includes R and the tidyverse packages. The tag specifies the specific version of R used in the image. These images are all based off of the Debian OS.
[The Rocker Project](https://www.rocker-project.org/): Docker Containers for the R Environment.
```
https://hub.docker.com/r/rocker/rstudio
最新版是 4.1.1
$ docker pull rocker/rstudio:4.1.1
```
(3) Seurat 基础镜像
Seurat 官网 install 目录下最后几行(2021/10/1):
We provide docker images for Seurat via dockerhub.
To use as a base image in a new Dockerfile:
`FROM satijalab/seurat:latest`
```
https://hub.docker.com/r/satijalab/seurat
最新版是 4.0.5
$ docker pull satijalab/seurat:4.0.5
如果一直拉取失败,只能让 其他人/国外朋友 拉取后打包发过来,再导入。
打包为tar命令
$ docker save -o seurat_4.0.5.tar satijalab/seurat:4.0.5
由tar包导入的命令
$ docker load < seurat_4.0.5.tar
```
(4) 检查下载的镜像
```
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 20.04 ba6acccedd29 7 days ago 72.8MB
rocker/rstudio 4.1.1 089c6b053857 3 days ago 1.89GB
satijalab/seurat 4.0.5 3bf89a0bbbfb 3 days ago 3.67GB
```
本文使用最后一个,其他2个作为学习/测试用。
查看构建镜像所用过的命令
```
我们发现,镜像 satijalab/seurat:4.0.5 也是基于 rocker 项目的。
$ docker history satijalab/seurat:4.0.5
输出到文件查看,比较直观
$ docker history --no-trunc satijalab/seurat:4.0.5 > ~/tmp.txt
$ less -S ~/tmp.txt
```
## 2. 开始构建镜像
以下操作都是在 ~/dockerBuild/4.1.0/ 下进行。
(1) ubuntu 版的 [Rstudio](https://www.rstudio.com/products/rstudio/download-server/debian-ubuntu/) 安装方法
```
sudo apt-get install gdebi-core
wget https://download2.rstudio.org/server/bionic/amd64/rstudio-server-2021.09.0-351-amd64.deb
sudo gdebi rstudio-server-2021.09.0-351-amd64.deb
```
先下载该deb文件:
```
$ wget https://download2.rstudio.org/server/bionic/amd64/rstudio-server-2021.09.0-351-amd64.deb
```
(2) 学习 镜像中安装 Rstudio 的脚本
```
https://github.com/rocker-org/rocker-versioned2/blob/master/dockerfiles/rstudio_4.1.1.Dockerfile
FROM rocker/r-ver:4.1.1
LABEL org.opencontainers.image.licenses="GPL-2.0-or-later" \
org.opencontainers.image.source="https://github.com/rocker-org/rocker-versioned2" \
org.opencontainers.image.vendor="Rocker Project" \
org.opencontainers.image.authors="Carl Boettiger "
ENV S6_VERSION=v2.1.0.2
ENV RSTUDIO_VERSION=2021.09.0+351
ENV DEFAULT_USER=rstudio
ENV PATH=/usr/lib/rstudio-server/bin:$PATH
RUN /rocker_scripts/install_rstudio.sh
RUN /rocker_scripts/install_pandoc.sh
EXPOSE 8787
CMD ["/init"]
```
继续看 [/scripts/install_rstudio.sh](https://github.com/rocker-org/rocker-versioned2/blob/master/scripts/install_rstudio.sh) 关键语句:
```
dpkg -i rstudio-server-*-amd64.deb
rm rstudio-server-*-amd64.deb
```
(3) 写 Dockerfile
$ cat Dockerfile
```
FROM satijalab/seurat:4.0.5
ENV DEFAULT_USER=rstudio
ENV PASSWORD=123456
ENV UID=1001
ENV GID=1001
ADD rstudio-server-2021.09.0-351-amd64.deb /home/
COPY scripts/* /rocker_scripts/
RUN /rocker_scripts/install_Rstudio2.sh
EXPOSE 8787
ENTRYPOINT ["/rocker_scripts/docker-entrypoint.sh"]
CMD ["bash"]
```
用到的脚本文件:
$ cat scripts/install_Rstudio2.sh
```
#!/bin/bash
set -e
## 安装Rstudio
apt-get update && apt-get install -y gdebi-core \
psmisc sudo libclang-dev libpq5
Rstudio_version="2021.09.0-351"
cd /home && gdebi -n rstudio-server-${Rstudio_version}-amd64.deb && rm rstudio-server-${Rstudio_version}-amd64.deb
#cd /home && dpkg -i rstudio-server-${Rstudio_version}-amd64.deb && rm rstudio-server-${Rstudio_version}-amd64.deb
## 清理缓存
apt-get clean
rm -rf /var/lib/apt/lists/*
rm -rf /var/cache/*
```
$ cat scripts/docker-entrypoint.sh
```
#!/bin/bash
set -e
## 新增用户 rstudio,密码随机生成。为了保证文件权限一致,传递一下uid和gid
DEFAULT_USER=${DEFAULT_USER:-rstudio}
groupadd -g $GID user
useradd -s /bin/bash -d /home/${DEFAULT_USER} -m ${DEFAULT_USER} -u $UID -g $GID
## 设置密码
if [ "$PASSWORD" == "123456" ]
then
PASSWORD=`date|md5sum |head -c 10`
fi
echo "${DEFAULT_USER}:${PASSWORD}" | chpasswd
## 添加sudo权限
echo ${DEFAULT_USER}" ALL=(ALL:ALL) ALL" >> /etc/sudoers
## 输出用户名和初始密码
echo -e "user: ${DEFAULT_USER}\npassword: "${PASSWORD} "\n" \
"\033[31m WARNING! \033[m Please change your password as soon as possible! The default passwd is public!";
# 添加软链接
chown $uid:$gid /data/
ln -s /data/ /home/${DEFAULT_USER}/data
## 启动服务
service rstudio-server start
exec "$@"
```
(4) 开始构建
```
当前目录下文件结构:
$ tree .
.
|-- Dockerfile
|-- rstudio-server-2021.09.0-351-amd64.deb
`-- scripts
|-- docker-entrypoint.sh
`-- install_Rstudio2.sh
脚本要有可执行权限
$ chmod a+x scripts/docker-entrypoint.sh
$ chmod a+x scripts/install_Rstudio2.sh
```
构建
```
$ docker build -t seurat:4.0.5r1 ./
会有很多输出,除了出错信息,其他忽略。
时长取决于网速,2-5min。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
seurat 4.0.5r1 8dc106e85b8e 12 seconds ago 4.58GB
```
上传到 docker hub
```
加上用户名前缀:
$ docker tag 8dc1 dawneve/seurat:4.0.5r1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
seurat 4.0.5r1 8dc106e85b8e 42 minutes ago 4.58GB
dawneve/seurat 4.0.5r1 8dc106e85b8e 42 minutes ago 4.58GB
登录
$ docker login -u dawneve
Password:
WARNING! Your password will be stored unencrypted in /home/wangjl/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
上传: 总是失败,不确定能否上传。
$ docker push dawneve/seurat:4.0.5r1
查看
https://hub.docker.com/u/dawneve
镜像打包压缩
$ docker save dawneve/seurat:4.0.5r1 | gzip -c > seurat_4.0.5r1.tar.gz
-rw-r--r-- 1 wangjl docker 1.5G Oct 26 17:31 seurat_4.0.5r1.tar.gz
新机器导入gz包
$ gunzip -c seurat_4.0.5r1.tar.gz | docker load
```
## 3. 使用镜像
优化启动方式: 文件映射,关联用户 uid,guid
(1)在该用户的目录中新建文件夹,用于和 docker 容器共享文件,并持久化。
```
$ mkdir -p /home/${user}/data/dockerHome
```
(2)设置信息
- 指定端口号,推荐[6千, 6万]之间的整数,一个主机上一个端口号只能被一个进程使用,被占用了就换一个。
- 获取用户信息:username, uid 和 gid
```
$ port=10002 && user=${USER} && uid=`id ${user} -u` && gid=`id ${user} -g`
```
(3)启动容器,并在容器内新建用户 rstudio
```
$ docker run --name=Rs4 --rm -it -d -p ${port}:8787 \
--mount type=bind,source=/home/${user}/data/dockerHome/,target=/data/ \
-e UID=$uid -e GID=$gid \
seurat:4.0.5r1
```
- 可设定密码(-e PASSWORD=xxx),默认密码是随机生成10位字符串。
- 可设定用户名(-e DEFAULT_USER=xxx),默认 rstudio.
* 默认用户有sudo权限,可以在Rstudio的shell标签下执行sudo命令。
查看容器是否启动成功
```
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0fa4f3d02cd2 seurat:4.0.5r1 "/rocker_scripts/doc…" 4 minutes ago Up 4 minutes 0.0.0.0:10002->8787/tcp, :::10002->8787/tcp Rs4
```
(4) 网页登录
查看用户和密码
```
$ docker logs Rs4
user: rstudio
password: 21be20f8f9
WARNING! Please change your password as soon as possible! The default passwd is public!
查主机 ip: `$ ipconfig`
打开浏览器: http://IP:10002
```
安全警告:
- 宿主机文件夹 /home/${user}/data/dockerHome/ 是和容器内 /home/rstudio/data/ 绑定的(内容完全一致)。
* 所以只要把数据放到主机的 ~/data/dockerHome/ 中,在Rstudio中的 ~/data/ 即可看到。
- 反复读这句:容器内仅 /home/rstudio/data/ 数据会保留,其他数据都会随着容器的停止(关机/停电/异常/被杀掉...)而被【销毁】。
* 销毁就是删除!重要输出只保存到Rstudio的 ~/data/ 下。
- 初始密码全服务器的人都可以看到,可能有些间谍软件也能看到,请及时修改!
* 在 Rstudio 的 Terminal 修改密码 $ passwd
## 4. 经验教训
- 整个流程探索最费时间的就是固定步骤 apt update && apt install ...,可以使用多步构建。
- 反复重复构建的原因,是添加用户总是不对。这里花的时间太多,得不偿失。
* 完美是成功的敌人。能用即可,全局最节省时间是最优解。
* 下次构建其他镜像,只提供 `docker exec -it xx bash` 下的添加用户方法。