云计算课程实验
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

477 строки
19 KiB

10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
10 месяцев назад
  1. # Assignment 2 指南
  2. ## `******注意,实验结束请立即删除云主机,节省费用******`
  3. ## `******注意2,实验未结束且短期内不会继续实验,也请删除云主机。下次实验时重新创建******`
  4. ### 重要技巧:如果实验未结束,可以通过制作主机镜像来保存当前状态,下次实验时用这个镜像创建云主机,从当前状态开始继续实验。步骤如下
  5. - 关机并制作镜像。制作完成后删除云主机。![关机](img/assignment2/关机.png)![镜像](img/assignment2/镜像.png)
  6. - 下次从镜像创建云主机。![创建](img/assignment2/创建.jpeg)
  7. ## 实验内容
  8. - 安装Docker并测试:`实验步骤 一)`
  9. - 了解并学习简单的Docker指令:`实验步骤 二)`
  10. - 利用Docker部署一个简单的静态网页App :`实验步骤 三)`
  11. - 使用Dockerfile完成复杂应用的搭建:`实验步骤 四)`
  12. ## 实验要求(仔细看)
  13. - #### 完成所有步骤,并在实验报告([模板下载](file/assignment2/学号-实验二.docx))中完成穿插在本指南中的`作业1~作业4`(只需要截图)。实验报告上传至 https://send2me.cn/BE8lksd_/SFW2bPQc78aR-g
  14. - #### 实验报告上传deadline:`9月29日23:59`
  15. ## 使用产品
  16. 云主机uhost, 私有网络vpc,基础网络unet, 容器镜像库uHub
  17. ## 需要权限
  18. 云主机uhost, 基础网络unet,容器镜像库uhub,容器服务udocker
  19. ## 实验步骤
  20. ### 零)前期工作
  21. #### 请根据Assignment1的要求[创建云主机](Assignment1.md),并使用ssh远程登录(可以直接使用root用户进行后续操作;如果登录个人账户进行操作,遇到permission问题时需在命令前面加上sudo再运行)
  22. #### `Hint(重要):` 本实验需要访问云主机的host端口,请在本地使用`-L `命令将云主机的`32768、32769、8000、8080`四个端口映射到本地,具体命令可以参考如下:
  23. ```bash
  24. $ ssh root@你的云主机外网ip -L 32769:0.0.0.0:32769 -L 32768:0.0.0.0:32768 -L 8080:0.0.0.0:8080 -L 8000:0.0.0.0:8000
  25. ```
  26. ### 一)安装Docker并测试
  27. #### 1. Docker是什么?
  28. > 一个开放源代码项目,通过在Linux上提供**OS级虚拟化**的附加抽象层和自动化层,使**容器**内软件应用程序的部署自动化。
  29. #### 简单来说,Docker是一种工具,它使开发人员,系统管理员等可以轻松地在沙盒(称为*容器*)中部署其应用程序,以在主机操作系统运行。Docker的主要好处是,它允许用户将**具有所有依赖关系的应用程序打包到**用于软件开发**的标准化单元**中。与虚拟机不同,容器不具有高开销,因此可以更有效地利用基础系统和资源。
  30. #### 2. 在Linux上安装Docker环境
  31. > 直到几个版本之前,在OSX和Windows上运行Docker还是很麻烦的。但是,最近,Docker已投入大量资金来改善其用户在这些OS上的体验,因此,现在运行Docker是一个轻而易举的事。
  32. #### 这里只介绍如何在Linux上安装和运行Docker, 如果同学们想要在其他系统上尝试使用Docker,可以参考Docker官网给出的教程(如何在[Mac](https://docs.docker.com/docker-for-mac/install)、[Linux/Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu)或[Windows]([Windows](https://docs.docker.com/docker-for-windows/install))上使用Docker)
  33. 在安装 docker 时,除了本文档提供的方法,也可以访问 https://docs.docker.com/engine/install/centos/ 按照官方教程进行安装。
  34. #### a) 安装docker
  35. #### 推荐使用如下命令安装 docker
  36. ```bash
  37. $ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
  38. ```
  39. #### 如果遇到如下图所示错误,请先运行下面的命令后再重新安装 docker
  40. ```bash
  41. $ yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
  42. ```
  43. ![docker错误](img/assignment2/docker错误.jpeg)
  44. #### 按照提示将自己的用户加入docker的用户组(root 用户无需操作)
  45. ```bash
  46. $ sudo usermod -aG docker yourusername
  47. ```
  48. #### 基本的docker启动与查看状态命令如下
  49. ```bash
  50. $ service docker start
  51. $ service docker stop
  52. $ service docker restart
  53. $ service docker status
  54. ● docker.service - Docker Application Container Engine
  55. Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
  56. Active: active (running) since Mon 2020-10-05 21:34:37 CST; 1min 45s ago
  57. Docs: https://docs.docker.com
  58. Main PID: 1954 (dockerd)
  59. Tasks: 8
  60. Memory: 40.1M
  61. CGroup: /system.slice/docker.service
  62. └─1954 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
  63. ```
  64. ## **为保证试验正常进行,请根据以下步骤修改docker镜像源从默认镜像库改为ucloud镜像库**
  65. ### hint:docker镜像库中包含大量可用镜像,可以直接下载到本地使用,常用的镜像库比如https://hub.docker.com/
  66. #### 1.在 https://cloud.docker.com , 免费注册一个 Docker 账号。用以下命令登录`docker hub`,输入创建账号的用户名、密码
  67. ```bash
  68. $ docker login
  69. Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
  70. Username: linlinshe
  71. Password:
  72. WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
  73. Configure a credential helper to remove this warning. See
  74. https://docs.docker.com/engine/reference/commandline/login/#credentials-store
  75. Login Succeeded
  76. ```
  77. #### 出现`login succeeded`表示登陆成功
  78. #### 2.将如下内容写入`/etc/docker/daemon.json`中(没有此文件则需要新建. ps: 需保证`docker`已经运行过,否则会出现`/etc/docker`文件夹不存在)
  79. ```json
  80. {
  81. "registry-mirrors": ["https://uhub-edu.service.ucloud.cn","https://uhub.service.ucloud.cn","https://registry.docker-cn.com","http://hub-mirror.c.163.com"]
  82. }
  83. ```
  84. #### hint:可以使用`nano`命令直接在云主机上编辑daemon.json,使用方法请自行查找。也可以在本地用纯文本编辑器(如txt)编辑,然后上传到云主机。
  85. #### 之后重新启动`docker`即可
  86. #### b) 测试Docker是否安装成功
  87. #### 当你的按照上述步骤安装完docker之后,可以通过运行如下命令来测试docker是否安装成功
  88. ```bash
  89. $ docker run hello-world
  90. Hello from Docker.
  91. This message shows that your installation appears to be working correctly.
  92. ...
  93. ```
  94. 如果 docker run 报错,可以尝试先 `docker pull hello-world` 拉取镜像以后再 docker run 。
  95. #### 3. 尝试使用busybox
  96. > 到此为止,你的docker环境已经安装完成并且正常运行,接下来我们尝试一些更加复杂的工作
  97. #### 在这个部分,我们将要通过`docker run`命令去开启一个`BusyBox container`
  98. #### a) 首先,我们通过运行如下命令从镜像库拉取`BusyBox`的镜像:
  99. ```bash
  100. $ docker pull busybox
  101. ```
  102. > 如果运行过程中遇到 **permission denied** 此类的错误,可以尝试在命令前加入 **sudo** 命令
  103. #### b) **pull** 命令可以将`busybox image`从docker仓库中拉取到本地,你可以使用**docker image**命令查看系统上目前已有的**image**.
  104. ```bash
  105. $ docker images
  106. REPOSITORY TAG IMAGE ID CREATED VIRT
  107. busybox latest c51f86c28340 4 weeks ago 1.10
  108. ```
  109. #### c) 我们接下来继续尝试使用`docker run`命令来运行`busybox`
  110. ```bash
  111. $ docker run busybox
  112. $
  113. ```
  114. #### d) 可以发现命令运行完,什么也没有发生。这不是bug,当我们执行`docker run`命令时,docker会从本地查找`image`,然后加载`image`生成`container`容器,并在其中运行command。正因为我们没有运行任何command,此容器没有任何输出。让我们加入自定义的command再试一次。
  115. ```bash
  116. $ docker run busybox echo "hello from busybox"
  117. hello from busybox
  118. ```
  119. ##### hint:通常,docker image不在运行时叫image,加载运行以后叫container
  120. `**************作业1:请将上述涉及docker run/image的操作界面截图,并插入实验报告中***************`
  121. ### 二) 熟悉Docker指令
  122. #### 让我们来尝试不同的**docker command**
  123. #### 1. docker ps
  124. > **docker ps** 命令可以查看当前正在运行的所有容器的状态,包括`CONTAINER ID`、`IMAGE`、`COMMAND`、`CREATE (创建时间)`、`STATUS (容器状态)`
  125. #### 让我们查看目前有哪些容器正在运行
  126. ```bash
  127. $ docker ps
  128. CONTAINER ID IMAGE COMMAND CREATED STATUS
  129. ```
  130. #### 可以看到控制台输出了了一个空的列表,这是正常的,因为目前没有容器正在运行。如果需要查看包括不在运行的所有容器,我们可以加入 **-a** 参数
  131. ```bash
  132. $ docker ps -a
  133. CONTAINER ID IMAGE COMMAND CREATED STATUS
  134. 305297d7a235 busybox "uptime" 11 minutes ago Exited (
  135. ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (
  136. 14e5bd11d164 hello-world "/hello" 2 minutes ago Exited (
  137. ```
  138. #### Wow~ 之前运行过的容器全部都出现在输出中了~
  139. #### 2. docker run -it
  140. > **docker run -it** 可以在我们创建 **container** 的同时,以交互式的形式获取到 **container shell** 的控制权. 我们可以在**docker run **命令中使用**--name custom_name** 来指定container的名称,若不指定,docker会为我们随机生成一个名字
  141. #### 接下来我们使用 **run -it** 命令来创建一个 `busybox container`,并在其中运行几个linux命令(回想:容器是一个虚拟化的环境,里面也运行了一个"轻量级的操作系统")
  142. ```bash
  143. $ docker run -it busybox sh
  144. / # ls
  145. bin dev etc home proc root sys tmp usr var
  146. / # uptime
  147. 05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
  148. / # cd home && pwd
  149. /home
  150. / # exit
  151. ```
  152. #### 3. docker rm
  153. > **docker rm -args** 可以删除不在运行的**container**,`args`可以是**container name/id** (可以不写完整,但必须保证唯一)
  154. #### 下面让我们尝试删除上面的两个**busybox container**
  155. ```bash
  156. $ docker rm 305297d7a235 ff0a5c3750b9
  157. 305297d7a235
  158. ff0a5c3750b9
  159. ```
  160. #### 也可以通过如下命令删除
  161. ```bash
  162. $ docker rm 305 ff
  163. 305297d7a235
  164. ff0a5c3750b9
  165. ```
  166. #### 现在使用`ps`命令检查一下是否删除成功吧!
  167. `**************作业2:请手动创建centos image的container,将终端命令和`container cpu`信息截图,并插入实验报告中***************`
  168. > Hint1: image名称即为centos
  169. > Hint2: 可以使用**lscpu**命令在container中查看linux的硬件信息,显示界面大致如下
  170. ```bash
  171. $ lscpu
  172. Architecture: x86_64
  173. CPU op-mode(s): 32-bit, 64-bit
  174. Byte Order: Little Endian
  175. CPU(s): 4
  176. On-line CPU(s) list: 0-3
  177. Thread(s) per core: 1
  178. Core(s) per socket: 1
  179. Socket(s): 4
  180. Vendor ID: GenuineIntel
  181. CPU family: 6
  182. Model: 158
  183. Model name: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  184. Stepping: 9
  185. CPU MHz: 2800.000
  186. BogoMIPS: 5616.00
  187. L1d cache: 32K
  188. L1i cache: 32K
  189. L2 cache: 256K
  190. L3 cache: 6144K
  191. ...
  192. ```
  193. ### 三) 使用docker创建静态webapp
  194. #### `docker`与虚拟机不同之处在于,在部署复杂的应用时,`docker`可以灵活的从`docker hub`中`pull`各种`image`(如:`mysql`、`sqlserver`、`java`、`php`.etc.),并将它们自由的组合到一起,使得每个`container`都能发挥自己独特的作用。那么我们先从简单的部署单页面的静态网页开始吧!
  195. #### 1. 运行`static-web app`
  196. #### `docker hub`上有许多开发者们上传的`image`,我们可以自由下载并且使用,这里我们使用到的`image`是`cloud_computing/static_site`,这是一个搭载了简单的静态单页面的Nginx镜像,让我们来试者运行它:
  197. ```bash
  198. $ docker run --rm cloud_computing/static_site
  199. Nginx is running...
  200. ```
  201. > `--rm` 参数的作用是当container运行结束时系统自动删除该container
  202. #### 如果顺利的话,你的终端会出现`nginx is running...`,但是目前容器对我们来说是一个完全封闭的环境,我们并没有办法去访问`container`的端口。按'ctrl+c'可以结束并退出容器。
  203. #### 2. 将`container`映射到本地
  204. 到此为止,我们已经部署了一个静态的`nginx container`但是并没有办法去访问,`docker`提供了许多接口去解决这个问题,我们可以通过添加参数的方式将`container`的端口或者文件夹映射到本地
  205. #### docker提供了如下一些参数
  206. | -d | 将container置于后台运行 |
  207. | :---------------------------: | :----------------------------------------------------------: |
  208. | -p local_port:container_port | 将container 的某个端口映射到本地 |
  209. | -P | 将container所有正在监听的端口全部映射到本地的随机端口 |
  210. | -v local_path:contatiner_path | 将本地的local_path文件夹映射到container的container_path文件夹并保持同步 |
  211. `**关于-v参数的说明,当你使用到-v 参数时,如**`
  212. ```bash
  213. docker run -d -v /home/data:/var/data --name test ubuntu
  214. ```
  215. `**那么相当于你将本地的/home/data目录映射到container的/var/data目录,container的/var/data目录会和你的本地目录保持同步,同时,若/var/data目录不存在,docker会自动创建,反之,目录中的内容会被全部覆盖掉(和本地的/home/data保持同步),希望同学们好好理解**`
  216. #### `static-site`默认监听的`80`和`443`端口我们使用上述参数尝试将它映射到本机
  217. ```bash
  218. $ docker run -d -P --name static_site cloud_computing/static_site
  219. e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
  220. ```
  221. #### 查看docker给我们映射的端口
  222. ```
  223. $ docker port static_site
  224. 80/tcp -> 0.0.0.0:32769
  225. 443/tcp -> 0.0.0.0:32768
  226. ```
  227. #### 可以看到`docker`将`container`的`80`和`443`分别映射到了本机的`32769`和`32768`两个端口上
  228. #### 3.打开浏览器,访问`http://localhost:32769`,得到如下页面:(若`docker`随机映射端口不是`32768/32769`可以无需验证此步骤)
  229. ![static-web](img/assignment2/static-web.png)
  230. `**************作业3:尝试使用-v、--rm和-p (请将container的80端口映射到host的8000端口)等参数,创建cloud_computing/static_site容器,并按照下述步骤6的要求截图,插入实验报告中***************`
  231. #### 具体步骤如下:
  232. #### 1.若提示continer正在运行中,可以使用`docker stop static_site && docker rm static_site`删除正在使用的容器并重新创建.
  233. #### 2. 创建`/var/html`文件夹
  234. ```bash
  235. mkdir /var/html
  236. ```
  237. #### 3.在`/var/html`中新建`index.html`文件,复制[index.html文件](file/assignment2/index.html)中的内容到文件中,并修改以下部分为自己的信息
  238. ```html
  239. <div class="container">
  240. <div class="row">
  241. <div class="one-half column" style="margin-top: 25%">
  242. <h4>Hello Docker!</h4>
  243. <p>This is being served from a <strong>docker</strong> container running Nginx.</p>
  244. <p>my id is xxxx,my name is xxx</p>
  245. </div>
  246. </div>
  247. </div>
  248. ```
  249. #### 4. 尝试使用`-p、-v、-d、--rm、--name`参数创建`cloud_computing/static_site`的`container`,具体要求为:映射`container`的`80`端口到`host`的`8000`端口,映射`container`的`/usr/share/nginx/html/mypage`路径到`/var/html`文件夹,`container`名称以自己的学号命名
  250. #### 5.访问本地浏览器:`http://localhost:8000/mypage/index.html`,若该端口访问不了,可查看ucloud防火墙查看是否开放了该端口号。若未开放,则可创建防火墙,设置所需的开放端口
  251. #### 6.将浏览器界面包括url截图,将创建container的终端界面截图,并插入到实验报告中 (浏览器界面类似下面图片所示)
  252. ![浏览器界面](img/assignment2/static-web-2-1.png)
  253. ### 四) 熟悉Dockerfile的简单使用
  254. #### 到现在为止,同学可能会疑惑,这种docker的镜像到底是如何创建的呢?这里就要使用到一个概念: `Dockerfile`
  255. #### 1.从repo中下载[附件](file/assignment2/demo2.zip),通过在本地运行`scp`命令上传到云服务器并解压
  256. ```bash
  257. $ scp -r path\demo.zip root@113.31.105.65:~
  258. root@113.31.105.65's password:
  259. demo.zip 100% 1308 142.4KB/s 00:00
  260. $ unzip demo.zip
  261. Archive: demo.zip
  262. creating: demo/
  263. inflating: __MACOSX/._demo
  264. inflating: demo/Dockerfile
  265. inflating: demo/app.py
  266. ```
  267. #### 2.查看Dockerfile
  268. #### 这是一个`Flask App`,是一个用`python`写的网页应用,我们进入`demo`文件夹,只有两个文件`app.py、Dockerfile`
  269. #### 首先我们使用`cat app.py`命令查看`app.py`的内容,显示如下:
  270. ```python
  271. from flask import Flask
  272. app = Flask(__name__)
  273. @app.route('/')
  274. def hello():
  275. return 'hello world!'
  276. if __name__ == '__main__':
  277. app.run(host='0.0.0.0')
  278. ```
  279. #### 看不懂没有关系,这就是一个很简单的flask应用,它定义了一个路由,当我们访问:`http://localhost:5000/`的时候,浏览器会给我们返回`hello world!`
  280. #### 接下来我们继续查看`Dockerfile`:
  281. ```dockerfile
  282. # 拉取python镜像作为基本环境
  283. FROM cloud_computing/python:latest
  284. # 设置额外信息
  285. LABEL description="Dockerfile Demo for ECNU"
  286. # 在container中运行命令(这一步在container安装pip依赖)
  287. RUN pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
  288. # 将本地目录拷贝到container并且设置为工作目录
  289. ADD ./app.py /opt
  290. WORKDIR /opt
  291. # 将5000端口暴露出来
  292. EXPOSE 5000
  293. # 容器启动的执行命令
  294. CMD python app.py
  295. ```
  296. #### 可以看出`Dockerfile`的书写非常简单易懂,涉及到几个命令
  297. | FROM | 指定容器来自的镜像 |
  298. | :-----: | :----------------------------------------------------------: |
  299. | RUN | 容器中运行shell命令 |
  300. | ADD | 将本地文件传送到容器指定位置 |
  301. | WORKDIR | 将容器中某个目录设置为工作目录(当前目录) |
  302. | EXPOSE | 将容器中某个端口暴露出来(如上述flask工作在5000端口,将其暴露出来) |
  303. | CMD | 容器启动自动执行的shell命令 |
  304. | LABEL | 设置一些额外的信息 |
  305. #### 通过`dockerfile`的方式,我们就可以将各种各样的环境打包成镜像上传到`docker hub`上供他人使用
  306. #### 3.打包镜像
  307. #### 在当前目录(`Dockerfile`同级目录),执行如下命令,`docker`会自动将当前环境部署打包为一个`image`
  308. ```bash
  309. $ docker build -t user-name/image-name .
  310. ```
  311. #### 通过上面的命令,我们就在本地打包好了一个名叫`username/image-name`的镜像,可以通过`docker images`命令查看是否创建成功。我们可以通过之前学习的`docker run`命令去创建该镜像的`container`
  312. `**************作业4:利用dockerfile将当前环境打包为 `英文姓名/demo` 的`image`,并通过`docker`命令将创建该镜像的`container`,将`5000`端口映射到本地的`8080`端口。将打包镜像的命令、创建容器的命令以及浏览器页面截图,并插入实验报告中***************`