项目已开源

笔者已将构建步骤整理成Dockerfile,欢迎使用。
地址: 云开发环境(dev-cloud)(记得给笔者点个star)

下面讲解怎么徒手打造云开发环境。

生产资料准备

  • 一台服务器
  • 注册域名 (这一步可跳过)
  • 一台开发机 (笔者是 macbook pro)

查看服务器系统版本

  • 查看系统内核版本号及系统名称
    1
    2
    uname -a          #命令1
    cat /proc/version #命令2

笔者的系统版本:x86_64 GNU/Linux

安装docker

使用官方脚本自动安装

1
2
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

启动docker

1
2
sudo systemctl enable docker #开机自动启动
sudo systemctl start docker

centos官方安装教程

安装Docker基础镜像

笔者使用Docker官方镜像 ubuntu:18.04

1
docker pull ubuntu:18.04

挂载卷配置

创建挂载卷:docker volume create [卷名]

运行容器

1
docker run -itd --name [容器名] -p 9999:22 -p 9980:3000 --mount source=[挂载卷],target=/mnt ubuntu:18.04

其中,99999980 是服务器暴露的端口号,22 是容器内部 SSH 暴露的端口号,3000 是容器内部暴露的端口号。

进入容器操作

1
docker exec -it [容器名] /bin/bash

设置容器ubuntu系统的root密码

1
passwd root

更新apt源

打开/etc/apt/sources.list,更新为以下配置(阿里云镜像源)

1
2
3
4
5
6
7
8
9
10
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
# deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
# deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

安装软件

安装软件vimopenssh-server

1
2
3
apt-get update
apt-get install vim # 编辑文件用
apt-get install openssh-server #ssh服务

修改ssh配置

1
vim /etc/ssh/sshd_config

修改文件对应的行

1
2
3
4
#PermitRootLogin prohibit-password #注释掉这一行
PermitRootLogin yes #允许root账号用于ssh登录

AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 #开放这一行

重新启动ssh

1
2
3
service ssh restart
# 或使用
# /etc/init.d/ssh restart

开放服务器端口

笔者使用的是“宝塔”进行端口管理,所以只要在宝塔后台,开启 99999980 端口访问即可。

验证

远程连接

1
ssh -p 9999 root@[服务器ip]

登录结果如下:

1
2
3
4
5
6
7
8
9
10
11
root@**'s password:
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 4.18.0-147.8.1.el8_1.x86_64 x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.
Last login: Tue Nov 1 07:17:38 2022 from **

VS Code remote-ssh插件

打开 IDE VS Code ,安装插件

修改本地机器的ssh配置

config文件中,增加配置如下:

1
2
3
4
host hehe
hostname [服务器ip地址]
user root
port 9999

然后,开启新窗口连接到容器

根据提示,输入密码即可

点击打开文件夹,效果如下:

这样,就可以愉快地在云端做开发了。

配置免密登录

  1. 生成公钥

    1
    ssh-keygen -t rsa -f ~/.ssh/id_rsa.self -C "邮箱"
  2. 将本地机器的公钥上传到容器

    1
    ssh-copy-id -i ~/.ssh/id_rsa.self.pub -p 9999 root@[服务器ip地址]
  3. 如果想要免密登录宿主机服务器,也可以把公钥上传到服务器

    1
    ssh-copy-id -i ~/.ssh/id_rsa.self.pub root@[服务器ip地址]
  4. 配置本地机器的~/.ssh/config文件

1
2
3
4
5
host hehe
hostname [服务器ip地址]
user root
port 9999
IdentityFile ~/.ssh/id_rsa.self

验证

登录容器

1
ssh root@[服务器ip地址] -p 9999

ssh-copy-id命令简介

ssh-copy-id 是使用ssh方式登陆到远程服务器的脚本。
作用是:把本地的ssh公钥安装到远程主机对应的账户下。
具体操作是将公钥填充到一个远程服务器的~/.ssh/authorized_keys文件中。

安装node

使用apt安装,更加便捷。
安装版本列表

1
curl -fsSL https://deb.nodesource.com/setup_14.x | bash - && apt-get install -y nodejs

安装nvm

由于国内访问不到github,所以需要将文件先下载到本地,然后再上传到服务器

下载nvm项目

1
git clone https://github.com/cnpm/nvm.git

scp上传到容器的~/.nvm

1
scp -P [端口] -r [本地文件路径] root@[服务器ip地址]:[服务器文件路径]

激活nvm

1
2
echo ". ~/.nvm/nvm.sh" >> /etc/profile 
source /etc/profile

nvm更换为国内镜像

1
vi ./root/.bashrc

在文件末尾加上以下语句:

1
export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node

重新加载环境变量:

1
source ~/.bashrc

检验是否生效:

1
echo $NVM_NODEJS_ORG_MIRROR

nvm ls-remoteN/A的解决:

1
2
echo "-k" > ~/.curlrc
export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt #unbuntu的解决方式

更换npm源

1
npm config set registry https://registry.npmmirror.com

安装yarn(非必要步骤)

1
2
3
corepack enable 
corepack prepare yarn@3.2.4 --activate
yarn -v #验证

设置国内镜像

1
yarn config set npmRegistryServer https://registry.npmmirror.com

更新端口映射(非必要步骤)

 如果想修改端口映射,可按此步骤操作

  1. 停止docker容器

    1
    docker stop [container id]
  2. commit该容器,作为新的镜像

    1
    docker commit [container id] [new image name]:[tag]
  3. 使用第二步生成的镜像,重新起一个容器

    1
    docker run -itd --name [容器名] -p 9999:22 -p 9980:3000 [new image name]:[tag]
  4. 进入容器操作

    1
    docker exec -it [容器名] /bin/bash
  5. 设置容器ubuntu的root密码

    1
    passwd root

ps: 如果之前的旧容器,已经配置免密登录的公钥,则不用重新配置,因为公钥还存在

开发示例

/mnt/文件夹下,新建项目(/mnt/文件已定义为挂载卷,相关文件不会记录到docker容器存储层中)

1
2
3
npx create-react-app my-app
cd my-app
npm start

web页面服务起来后,端口是 3000

服务器需要映射 9980 到 容器的 3000 端口。

然后,就可以在本机浏览器使用 localhost:3000http://ip:9980 的方式访问到页面。
其中 localhost:3000 是由 VS Code 做了 SSH隧道 转发。将容器的 3000 端口内容,转发到本地端口,所以可以在本地访问到。

具体可查看官方文档 Forwarding a port / creating SSH tunnel

拓展

VS Code之所以能进行端口转发,是使用了SSH隧道转发技术
SSH隧道转发技术可以通过22号端口,访问远程服务器上的其他未公开端口。

举个例子:
使用以下命令,可以将远程的5432端口映射到本地:

1
ssh -f ${ user }@${ ip } -L 0.0.0.0:5432:0.0.0.0:5432 -N

配置开发域名

笔者使用的是阿里云服务器,所以需要在阿里云后台,设置DNS解析规则,解析到docker容器所在的服务器IP。

使用的开发域名为:dev.wangxiaokai.vip

接着,配置nginx转发规则

1
2
3
4
5
6
7
8
9
10
11
12
server{
listen 80;
server_name dev.wangxiaokai.vip;
index index.php index.html index.htm;

location / {
proxy_pass http://127.0.0.1:9980; # 转发规则
proxy_set_header Host $proxy_host; # 修改转发请求头,让9980端口的应用可以接收到真实的请求
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

重启下nginx生效配置。

遇到的问题

解决监听文件数的限制

1
[ERROR] Error: ENOSPC: System limit for number of file watchers reached

docker会继承主机上的一些设置文件,为了防止影响全局,上述文件在docker中会被设置为read-only。
所以需要到宿主机上去更改以上配置。
主机更改完成后,docker就会自动继承了。

在容器的宿主机,执行以下命令

1
2
3
4
5
6
7
8
# insert the new value into the system config
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

# check that the new value was applied
cat /proc/sys/fs/inotify/max_user_watches

# config variable name (not runnable)
fs.inotify.max_user_watches=524288

解决中文乱码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装中文支持包
apt-get install -y language-pack-zh-hans

# 安装时区数据库
apt-get install -y locales tzdata

locale-gen zh_CN.UTF-8

update-locale LANG=zh_CN.UTF-8 LANGUAGE=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8

# 建立到期望的时区的链接
ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 重新配置tzdata软件包,使得时区设置生效
dpkg-reconfigure --frontend noninteractive tzdata

参考