2016
Nov
27

如何使用 Docker 建立一个 Linux Server (CentOS 7) 呢 ,我要用 Docker 建一个 Linux container ,并且让我可以从远端登入这个 container ,把它当作一台 Linux Server 开发机。

如果你还不知道 Docker 是什么,请先阅读以下文章:

在没有 Docker 以前,我时常用 VirtualBox 装一台Linux Server 拿来当做开发机,甚至我曾经用 VirtualBox 的机器当线上环境使用,会使用 VirtualBox 最重要的原因是很容易还原整个环境,假如今天我的机器硬碟坏掉了,那么我只要再买一颗硬碟,装上 OS 与 VirtualBox ,再把备份的 VirtualBox Image 复制过来就完成了系统还原。

新技术 Docker 现在已经可以取代 VirtualBox 大部分的功能,而且效能比 VirtualBox 好,最棒的是 Docker 可以用 Terminal 来操作,完全不需要使用到 GUI 介面,我只要用 SSH client 登入 OS ,就能单靠指令来完成 Docker container 任何作业, VirtualBox 理论上也可以用指令来完成所有作业,只是 VirtualBox 的指令有点难懂,而且网路上的文件很少。


建立 Centos 7 Contatiner

我们要先建立一个 Dockerfile ,这支 Dockerfile 会执行以下指令:

Dockerfile for logining linux
  1. FROM centos
  2. RUN yum install -y sudo wget telnet openssh-server vim git
  3. RUN useradd puritys
  4.  
  5. COPY files/authorized_keys /home/puritys/.ssh/
  6. COPY files/start.sh /root/
  7.  
  8. # Enable sshd
  9. COPY files/sshd_config /etc/ssh/
  10. RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
  11.  
  12. # Add account into sudoers and this account don't need to type password
  13. COPY files/sudoers /etc/
  • 第 1 行:安装 Centos 。
  • 第 3 行:用 yum 安装常用的软体 。
  • 第 4 行:建立一个帐号,我的帐号是 "puritys" ,你要改成你自已的帐号 。
  • 第 6 行:复制 authorized_keys 这个档案,这个档案主要是用来给 ssh private key 登入
  • 第 7 行:复制 /root/start.sh ,这个 script 主要是写下 container 开机时要启动的 command ,因为 Docker 预设开机是不会执行任何程式,我们必须要手动执行写好的 script ,还记得我们需要 Remote Login 的功能吗, Remote Login 的功能需要启动 sshd 这个程式,后面会说明 start.sh 要写些什么。
  • 第 10 行:复制 /etc/sshd_config ,这个档案是 sshd 的设定档。
  • 第 11 行: 产生一组 sshd 专用的 rsa private key 。
  • 第 14 行: 复制 /etc/sudoers , 这个档案是 sudo 的设定档,登入 container 后,我们会需要用到 sudo 的功能,所以要修改 /etc/sudoers 的设定。

authorized_keys

第 6 行的 authorized_keys 这个档案存的资料是 public key ,你可以用 ssh-keygen -t rsa -b 4096 这个指令建立 private/public key ,成功建立后,你会看到两个档案,分别是 id_rsa, id_rsa.pub ,而 authorized_keys 就是 id_rsa.pub 。

ssh-keygen
  1. > ssh-keygen -t rsa -b 4096
  2. Generating public/private rsa key pair.
  3. Enter file in which to save the key (/Users/account/.ssh/id_rsa):
  4. Enter passphrase (empty for no passphrase):
  5. Enter same passphrase again:
  6. Your identification has been saved in id_rsa.
  7. Your public key has been saved in id_rsa.pub.
  8. The key fingerprint is:
  9. ---
  10. The key's randomart image is:
  11. +--[ RSA 4096]----+
  12. | .oo. + |
  13. | o =.* |
  14. | z..oB + |
  15. | ..o = . |
  16. | z. o c |
  17. | . . + |
  18. | . S |
  19. | |
  20. | |
  21. +-----------------+

sshd_config

还记得第 3 行 yum 安装的软体吗,其中一个 openssh-server 就是 sshd 的软体,必需先安装这个软体,我们才能远端登入 container 。

我建立的 container 不希望有 "登入打密码" 的功能,只要开放 ssh private key 登入功能即可,所以我要覆写原有的 sshd_config ,把 ChallengeResponseAuthentication, PasswordAuthentication, PermitEmptyPasswords 这三个值设成 no 。

sshd_config
  1. HostKey /etc/ssh/ssh_host_rsa_key
  2. SyslogFacility AUTHPRIV
  3.  
  4. RSAAuthentication yes
  5. PubkeyAuthentication yes
  6. AuthorizedKeysFile .ssh/authorized_keys
  7.  
  8. ChallengeResponseAuthentication no
  9. PasswordAuthentication no
  10. PermitEmptyPasswords no
  11.  
  12. UsePAM yes
  13. X11Forwarding yes
  14. UsePrivilegeSeparation sandbox
  15.  
  16. AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
  17. AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
  18. AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
  19. AcceptEnv XMODIFIERS
  20.  
  21. # override default of no subsystems
  22. Subsystem sftp /usr/libexec/openssh/sftp-server

sudoers

第 14 行的 COPY sudoers ,如何要使用 sudo 的功能,就要安装 sudo 这个软体,所以 Dockerfile 第 3 行的 yum 指令就已经包含了 yum install sudo ,另一个问题是,一般我们在使用 sudo 的时候,系统会要求我们输入密码,但是我们新建的帐号并没有密码,所以我要在 sudoers 档案里加入一行 "puritys ALL=(ALL) NOPASSWD:ALL",让我的帐号在执行 sudo 时,可以不用输入密码 (记得把 puritys 改成你的帐号)。

/etc/sudoers
  1. Defaults requiretty
  2. Defaults !visiblepw
  3.  
  4. Defaults always_set_home
  5.  
  6. Defaults !env_reset
  7.  
  8. Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
  9. root ALL=(ALL) ALL
  10. %wheel ALL=(ALL) ALL
  11.  
  12. puritys ALL=(ALL) NOPASSWD:ALL

start.sh

第 7 行的 start.sh ,这是指开机启动要执行的程式,因为我只需要启动 sshd ,所以加入 "/usr/sbin/sshd -D&" 就行罗。

start.sh
  1. #!/bin/bash
  2. /usr/sbin/sshd -D&

把上述的档案都放都 files/ 这个资料夹下即可,请比对下图的档案结构,是否每个档案都存在,再来就要建立我们设定的这台 docker image。

tree
  1. ├―― centos7
  2. │ ├―― Dockerfile
  3. │ ├―― files
  4. │ │ ├―― authorized_keys
  5. │ │ ├―― sshd_config
  6. │ │ ├―― start.sh
  7. │ │ └―― sudoers

建立 Docker Image

完成上述的档案建置后,我们要 build Docker Image ,再启动 Docker ,执行 start.sh ,然后用另一个帐号登入 container 。

首先我要设定两个变数,一个是 image name ,另一个是 container name ,因为接下来的指令都会一直用到这两个名字,所以习惯上我要建设定好变数。

Image/Container
  1. imageName=my/my-centos7
  2. containerName=my-centos7

使用 docker build 建立 Image。

  • docker build -t $(imageName) .

使用 docker run -d ,启动 container 并放在背景执行,再用 docker exec 执行开机启动档。

  • docker run -d -t -p 8001:22 --name $(containerName) $(imageName) /bin/bash
  • docker exec -d $(containerName) bash -c "sh /root/start.sh"

这两步做完之后,我们就成功启动了一台 Linux 环境,里面有我的帐号 puritys ,以及可以用来登入的 public key ,另外我用 "-p 8001:22" ,将Docker Host 8001 port 转到 container 22 port ,所以你只要知道 Docker Host 的 IP ,就可以用 8001 登入 container ,例如我会用下面这个 ssh 登入我的 container 。

ssh 192.168.99.100 -p8001

我习惯把所有的指令写在 Makefile ,这样不但可以避免忘记指令,也方便我组合各种不同的 Linux 指令,下面提供给大家参考:

Makefile
  1. imageName=my/my-centos7
  2. containerName=my-centos7
  3.  
  4. build:
  5. docker build -t $(imageName) .
  6.  
  7. stop:
  8. docker stop -f $(containerName) || true
  9. docker rm -f $(containerName) || true
  10.  
  11. start:
  12. make stop
  13. docker run -d -t -p 8001:22 --name $(containerName) $(imageName) /bin/bash
  14. docker exec -d $(containerName) bash -c "sh /root/start.sh"
  15.  
  16. root:
  17. make stop
  18. docker run -t -i -p 8001:22 --name $(containerName) $(imageName) /bin/bash
  19.  
  20. login:
  21. ssh [email protected] -p8001

回應 (Leave a comment)