云计算课程实验
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
14 KiB

4 years ago
  1. # Assignment 2 指南
  2. ## `******注意,实验结束请立即删除云主机,节省费用******`
  3. ## `******注意2,实验未结束且短期内不会继续实验,也请删除云主机。下次实验时重新创建******`
  4. ## 实验内容
  5. - 安装Docker并测试:`实验步骤 一)`
  6. - 了解并学习简单的Docker指令:`实验步骤 二)`
  7. - 利用Docker部署一个简单的静态网页App :`实验步骤 三)`
  8. - 使用Dockerfile完成复杂应用的搭建:`实验步骤 四)`
  9. ## 实验要求(仔细看)
  10. - #### 完成所有步骤,并在实验报告([模板下载](file/assignment1/学号-实验一.docx))中完成穿插在本指南中的`作业1~作业4`(只需要截图)。实验报告转成`“学号-实验二.pdf”`,并上传至http://113.31.104.68:3389/index.htm
  11. - #### 实验报告上传deadline:`10月xx日`
  12. ## 使用产品
  13. 云主机uhost, 私有网络vpc,基础网络unet, Docker相关技术
  14. ## 需要权限
  15. 云主机uhost, 基础网络unet
  16. ## 实验步骤
  17. ### 零)前期工作
  18. #### 请根据Assignment1的要求[创建云主机](Assignment1.md),并使用ssh远程登录(可以直接使用root用户进行后续操作)
  19. ### 一)安装Docker并测试
  20. #### 1. Docker是什么?
  21. > 一个开放源代码项目,通过在Linux上提供**OS级虚拟化**的附加抽象层和自动化层,使**容器**内软件应用程序的部署自动化。
  22. #### 简单来说,Docker是一种工具,它使开发人员,系统管理员等可以轻松地在沙盒(称为*容器*)中部署其应用程序,以在主机操作系统(即Linux)上运行。Docker的主要好处是,它允许用户将**具有所有依赖关系的应用程序打包到**用于软件开发**的标准化单元**中。与虚拟机不同,容器不具有高开销,因此可以更有效地利用基础系统和资源。
  23. #### 2. 在Linux上安装Docker环境
  24. > 直到几个版本之前,在OSX和Windows上运行Docker还是很麻烦的。但是,最近,Docker已投入大量资金来改善其用户在这些OS上的入职体验,因此,现在运行Docker是一个轻而易举的事。
  25. #### 这里只介绍如何在Linux上安装和运行Docker, 如果同学们想要在其他系统上尝试使用Docker,可以参考Docker官网给出的教程(如何在[Mac](https://docs.docker.com/docker-for-mac/install)、[Linux](https://docs.docker.com/install/linux/docker-ce/ubuntu)或[Windows]([Windows](https://docs.docker.com/docker-for-windows/install))上使用Docker)
  26. #### a) 安装docker
  27. #### 推荐使用如下命令安装docker
  28. ```bash
  29. $ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
  30. ```
  31. #### 按照提示将自己的用户加入docker的用户组(root 用户无需操作)
  32. ```bash
  33. $ sudo usermod -aG docker your-user
  34. ```
  35. #### 基本的docker启动与查看状态命令如下
  36. ```bash
  37. $ service docker start
  38. $ service docker stop
  39. $ service docker restart
  40. $ service docker status
  41. ● docker.service - Docker Application Container Engine
  42. Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
  43. Active: active (running) since Mon 2020-10-05 21:34:37 CST; 1min 45s ago
  44. Docs: https://docs.docker.com
  45. Main PID: 1954 (dockerd)
  46. Tasks: 8
  47. Memory: 40.1M
  48. CGroup: /system.slice/docker.service
  49. └─1954 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
  50. ```
  51. ## **强烈推荐使用阿里云和三方源加速image下载,不然接下来的实验会进行的异常痛苦**
  52. #### 讲如下内容写入`/etc/docker/daemon.json`中(没有则创建)
  53. ```
  54. {
  55. "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"]
  56. }
  57. ```
  58. #### 之后重新启动`docker`即可
  59. #### b) 测试Docker是否安装成功
  60. #### 当你的按照上述步骤安装完docker之后,可以通过运行如下命令来测试docker是否安装成功
  61. ```bash
  62. $ docker run hello-world
  63. Hello from Docker.
  64. This message shows that your installation appears to be working correctly.
  65. ...
  66. ```
  67. #### 3. 尝试使用busybox
  68. > 到此为止,你的docker环境已经安装完成并且正常运行,接下来我们尝试一些更加复杂的工作
  69. #### 在这个部分,我们将要通过`docker run`命令去开启一个`BusyBox container`
  70. #### a) 首先,我们通过运行如下命令从互联网拉取`BusyBox Image`:
  71. ```bash
  72. $ docker pull busybox
  73. ```
  74. > 如果运行过程中遇到 **permission denied** 此类的错误,可以尝试在命令前加入 **sudo** 命令
  75. #### b) **pull** 命令可以将`busybox image`从docker仓库中拉取到本地,你可以使用**docker image**命令查看系统上目前已有的**image**.
  76. ```bash
  77. $ docker images
  78. REPOSITORY TAG IMAGE ID CREATED VIRT
  79. busybox latest c51f86c28340 4 weeks ago 1.10
  80. ```
  81. #### c) 我们接下来继续尝试使用`docker run`命令来运行`busybox`
  82. ```bash
  83. $ docker run busybox
  84. $
  85. ```
  86. #### d) 可以发现命令运行完,什么也没有发生。这不是bug,当我们执行`docker run`命令时,docker会从本地查找`image`,然后加载`image`并在容器中运行command。让我们加入自定义的command再试一次
  87. ```bash
  88. $ docker run busybox echo "hello from busybox"
  89. hello from busybox
  90. ```
  91. `**************作业1:请将上述涉及docker run/image的操作界面截图,并插入实验报告中***************`
  92. ### 二) 熟悉Docker指令
  93. #### 让我们来尝试不同的**docker command**
  94. #### 1. docker ps
  95. > **docker ps** 命令可以查看当前正在运行的所有容器的状态,包括`CONTAINER ID`、`IMAGE`、`COMMAND`、`CREATE (创建时间)`、`STATUS (容器状态)`
  96. #### 让我们查看目前有哪些容器正在运行
  97. ```bash
  98. $ docker ps
  99. CONTAINER ID IMAGE COMMAND CREATED STATUS
  100. ```
  101. #### 可以看到控制台输出了了一个空的列表,这是正常的,因为目前没有容器正在运行。如果需要查看包括不在运行的所有容器,我们可以加入 **-a** 参数
  102. ```bash
  103. $ docker ps -a
  104. CONTAINER ID IMAGE COMMAND CREATED STATUS
  105. 305297d7a235 busybox "uptime" 11 minutes ago Exited (
  106. ff0a5c3750b9 busybox "sh" 12 minutes ago Exited (
  107. 14e5bd11d164 hello-world "/hello" 2 minutes ago Exited (
  108. ```
  109. #### Wow~ 之前运行过的容器全部都出现在输出中了~
  110. #### 2. docker run -it
  111. > **docker run -it** 可以在我们创建 **container** 的同时,以交互式的形式获取到 **container shell** 的控制权. 我们可以在**docker run **命令中使用**--name custom_name** 来指定container的名称,若不指定,docker会为我们随机生成一个名字
  112. #### 接下来我们使用 **run -it** 命令来创建一个 `busybox container`:
  113. ```bash
  114. $ docker run -it busybox sh
  115. / # ls
  116. bin dev etc home proc root sys tmp usr var
  117. / # uptime
  118. 05:45:21 up 5:58, 0 users, load average: 0.00, 0.01, 0.04
  119. ```
  120. #### 3. docker rm
  121. > **docker rm -args** 可以删除不在运行的**container**,`args`可以是**container name/id** (可以不写完整,但必须保证唯一)
  122. #### 下面让我们尝试删除上面的两个**busybox container**
  123. ```bash
  124. $ docker rm 305297d7a235 ff0a5c3750b9
  125. 305297d7a235
  126. ff0a5c3750b9
  127. ```
  128. #### 也可以通过如下命令删除
  129. ```bash
  130. $ docker rm 305 ff
  131. 305297d7a235
  132. ff0a5c3750b9
  133. ```
  134. #### 现在使用`ps`命令检查一下是否删除成功吧!
  135. `**************作业2:请手动创建ubuntu:18.04 image的container并将cpu信息截图,并插入实验报告中***************`
  136. > Hint: 可以使用**lscpu**命令查看linux的硬件信息,显示界面大致如下
  137. ```bash
  138. $ lscpu
  139. Architecture: x86_64
  140. CPU op-mode(s): 32-bit, 64-bit
  141. Byte Order: Little Endian
  142. CPU(s): 4
  143. On-line CPU(s) list: 0-3
  144. Thread(s) per core: 1
  145. Core(s) per socket: 1
  146. Socket(s): 4
  147. Vendor ID: GenuineIntel
  148. CPU family: 6
  149. Model: 158
  150. Model name: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  151. Stepping: 9
  152. CPU MHz: 2800.000
  153. BogoMIPS: 5616.00
  154. L1d cache: 32K
  155. L1i cache: 32K
  156. L2 cache: 256K
  157. L3 cache: 6144K
  158. ...
  159. ```
  160. ### 三) 使用docker创建静态webapp
  161. #### `docker`与虚拟机不同之处在于,在部署复杂的应用时,`docker`可以灵活的从`docker hub`中`pull`各种`image`(如:`mysql`、`sqlserver`、`java`、`php`.etc.),并将它们自由的组合到一起,使得每个`container`都能发挥自己独特的作用。那么我们先从简单的部署单页面的静态网页开始吧!
  162. #### 1. 运行`static-web app`
  163. #### `docker hub`上有许多开发者们上传的`image`,我们可以自由下载并且使用,这里我们使用到的`image`是`prakhar1989/staticsite`,这是一个搭载了简单的静态单页面的Nginx镜像,让我们来试者运行它:
  164. ```bash
  165. $ docker run --rm prakhar1989/static-site
  166. Nginx is running...
  167. ```
  168. > `--rm` 参数的作用是当container运行结束时系统自动删除该container
  169. #### 如果顺利的话,你的终端会出现`nginx is running...`,但是目前容器对我们来说是一个完全封闭的环境,我们并没有办法去访问`container`的端口
  170. #### 2. 将`container`映射到本地
  171. 到此为止,我们已经部署了一个静态的`nginx container`但是并没有办法去访问,`docker`提供了许多接口去解决这个问题,我们可以通过添加参数的方式将`container`的端口或者文件夹映射到本地
  172. #### docker提供了如下一些参数
  173. | -d | 将container置于后台运行 |
  174. | :---------------------------: | :---------------------------------------------------: |
  175. | -p local_port:container_port | 将container 的某个端口映射到本地 |
  176. | -P | 将container所有正在监听的端口全部映射到本地的随机端口 |
  177. | -v local_path:contatiner_path | 将container的某个文件路径映射到本地 |
  178. #### `static-site`默认监听的`80`和`443`端口,我们使用上述参数尝试将它映射到本机
  179. ```bash
  180. $ docker run -d -P --name static-site prakhar1989/static-site
  181. e61d12292d69556eabe2a44c16cbd54486b2527e2ce4f95438e504afb7b02810
  182. ```
  183. #### 查看docker给我们映射的端口
  184. ```
  185. $ docker port static-site
  186. 80/tcp -> 0.0.0.0:32769
  187. 443/tcp -> 0.0.0.0:32768
  188. ```
  189. #### 可以看到`docker`将`container`的`80`和`443`分别映射到了本机的`32769`和`32768`两个端口上
  190. ####.打开浏览器,访问`http://localhost:32769`,得到如下页面:
  191. ![static-web](img/assignment2/static-web.png)
  192. `**************作业3:尝试使用-v、--rm和-p等参数,创建static-site容器,并以自己的学号命名,将container的/usr/share/nginx/html文件夹映射到当前目录的html文件夹,并修改index.html文件,加入自己的姓名和学号,并将上述步骤和本地目录接口截图插入实验报告中***************`
  193. > Hint:
  194. >
  195. > 1.若提示continer正在运行中,可以使用`docker stop static-site && docker rm static-site`删除正在使用的容器并重新创建.
  196. >
  197. > 2.-v local_path请使用绝对路径
  198. ### 四) 熟悉Dockerfile的简单使用
  199. #### 到现在为止,同学可能会疑惑,这种docker的镜像到底是如何创建的呢?这里就要使用到一个概念: `Dockerfile`
  200. #### 1.从repo中下载[附件](/file/assignment2/FoodTrucks.zip),通过`scp`命令上传到云服务器并解压
  201. ```bash
  202. $ scp FoodTrucks.zip root@113.31.112.166:~
  203. root@113.31.112.166's password:
  204. /etc/profile.d/lang.sh: line 19: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
  205. FoodTrucks.zip 0% 0 0.0KB/s --:-- ETAsFoodTrucks.zip 100% 1097KB 488.5KB/s 00:02
  206. $ unzip FoodTrucks.zip
  207. Archive: FoodTrucks.zip
  208. creating: FoodTrucks/
  209. inflating: __MACOSX/._FoodTrucks
  210. inflating: FoodTrucks/.DS_Store
  211. ...
  212. ```
  213. #### 2.查看Dockerfile
  214. #### 这是一个`Flask App`,是一个用`python`写的网页应用,我们使用`cat Dockerfile`命令查看`Dockerfile的内容`,显示如下:
  215. ```dockerfile
  216. # 基于ubuntu:18.04容器
  217. FROM ubuntu:18.04
  218. # 安装相关依赖
  219. RUN apt-get -yqq update
  220. RUN apt-get -yqq install python3-pip python3-dev curl gnupg
  221. RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
  222. RUN apt-get install -yq nodejs
  223. # 将本地目录拷贝到container并且设置为工作目录
  224. ADD flask-app /opt/flask-app
  225. WORKDIR /opt/flask-app
  226. # 安装node和python的相关依赖
  227. RUN npm install
  228. RUN npm run build
  229. RUN pip3 install -r requirements.txt
  230. # 将5000端口暴露出来
  231. EXPOSE 5000
  232. # 容器启动的执行命令
  233. CMD [ "python3", "./app.py" ]
  234. ```
  235. #### 可以看出`Dockerfile`的书写非常简单易懂,涉及到几个命令
  236. | FROM | 指定容器来自的镜像 |
  237. | :-----: | :----------------------------------------------------------: |
  238. | RUN | 容器中运行shell命令 |
  239. | ADD | 将本地文件传送到容器指定位置 |
  240. | WORKDIR | 将容器中某个目录设置为工作目录(当前目录) |
  241. | EXPOSE | 将容器中某个端口暴露出来(如上述flask工作在5000端口,将其暴露出来) |
  242. | CMD | 容器启动自动执行的shell命令 |
  243. #### 通过`dockerfile`的方式,我们就可以将各种各样的环境打包成镜像上传到`docker hub`上供他人使用
  244. #### 3.打包镜像
  245. #### 在当前目录(`Dockerfile`同级目录),执行如下命令,`docker`会自动将当前环境部署打包为一个`image`
  246. ```bash
  247. $ docker build -t user-name/image-name
  248. ```
  249. #### 这一步可能耗时较长,请耐心等待。。。
  250. **************作业4:利用dockerfile将当前环境打包为 `英文姓名`/food` 的`image`,并通过`docker`命令将创建该镜像的`container`,将`5000`端口映射到本地的`8080`端口。将打包命令和浏览器页面截图,并插入实验报告中***************