Docker部署--腾讯云和Mac
Docker是一个跨平台的轻量级容器,可移植性非常高,一次部署,终生可用。网上这方面的概述一大堆,就不细写了。这一套搭建下来,其实就是Docker镜像、Registry仓库、Docker容器。我们可以在本地自己生产镜像(下面会有具体操作),也可以直接下载别人或者官方的现成镜像,然后pull到Registry仓库(文中使用DockerHub(https://hub.docker.com/)是默认的 Registry,由 Docker 公司维护,上面有数以万计的镜像,用户可以自由下载和使用。)。这个时候我们可以在任何地方安装了Docker的地方push我们的镜像,build and run.....
腾讯云安装Docker
- 先登录腾讯云后台,可以直接登录后台,也可以用本地终端
ssh ubuntu@ip地址 //注意腾讯云用户名是ubuntu,不是root
再输入密码即可~
![](https://img.haomeiwen.com/i2868618/7066dfbef10f3406.png)
- 使用
sudo passwd root
设置root的密码 - 切换到root用户
ubuntu@VM-42-54-ubuntu:~$ su root
Password:
root@VM-42-54-ubuntu:/home/ubuntu#
- 在服务器下载Docker
官方安装指南
1.更新apt软件包索引。
$ sudo apt-get update
2.安装最新版本的Docker CE,或转到下一步安装特定版本。任何现有的Docker安装都会被替换。
$ sudo apt-get install docker-ce
在这里我遇到了错误E: Unable to locate package docker-ce
有人在stack overflow给出答案
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
sudo apt-get update
sudo apt-get install docker-ce
检测安装成功了没
root@VM-42-54-ubuntu:/home/ubuntu# docker version
Client:
Version: 17.12.1-ce
API version: 1.35
Go version: go1.9.4
Git commit: 7390fc6
Built: Tue Feb 27 22:17:40 2018
OS/Arch: linux/amd64
Server:
Engine:
Version: 17.12.1-ce
API version: 1.35 (minimum version 1.12)
Go version: go1.9.4
Git commit: 7390fc6
Built: Tue Feb 27 22:16:13 2018
OS/Arch: linux/amd64
Experimental: false
服务器Docker安装完毕~
Mac端安装Docker
官方下载地址谁用谁知道,整整下了我一下午!!!
百度云:链接:https://pan.baidu.com/s/1ppYSk24VfhUGS3XLHe4hZw 密码:9uly
根据晚上资料发现以前好像是使用了boot2docker或者docker toolbox。但现在docker for Mac全搞定了,也就不去查看以前的一些工具了。一键安装完毕后打开,右上角小鲸鱼出现了
![](http://upload-images.jianshu.io/upload_images/2868618-9cafac38280d7bf1.png)
打开终端:
localhost:~ ljb48229$ docker version
Client:
Version: 17.12.0-ce
API version: 1.35
Go version: go1.9.2
Git commit: c97c6d6
Built: Wed Dec 27 20:03:51 2017
OS/Arch: darwin/amd64
Server:
Engine:
Version: 17.12.0-ce
API version: 1.35 (minimum version 1.12)
Go version: go1.9.2
Git commit: c97c6d6
Built: Wed Dec 27 20:12:29 2017
OS/Arch: linux/amd64
Experimental: true
本地安装完毕~
注册Docker hub
官网注册自己的Docker ID
用来存放自己的镜像~
开始玩Docker
先在本地生成一个镜像,在pull到Dockerhub,然后在服务器push这个镜像,运行~
- 在本地列出已经下载下来的镜像,可以使用 docker images 命令。
localhost:~ ljb48229$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
可以看到现在本地的镜像没有。
现在将firstwenapp包打包成镜像~
![](http://upload-images.jianshu.io/upload_images/2868618-b1c00004d6f03752.png)
在main.go文件中
package main
import (
"fmt"
"net/http"
)
func handler(rw http.ResponseWriter, req *http.Request) {
fmt.Fprintf(rw, "hello world, %s", req.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
监听8080端口,访问时返回hello world + 请求参数
,功能很简单~
可以看到我们在项目根目录下增加了Dockerfile文件。
Dockerfile文件
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
FROM golang
ADD . $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp
WORKDIR $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp
RUN go install github.com/jiangboLee/go_web_study/firstwebapp
ENTRYPOINT /go/bin/firstwebapp
EXPOSE 8080
FROM 指定基础镜像
所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。而 FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。这里是指定golang的环境。
ADD
如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。
在 Docker 官方的最佳实践文档中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。
另外需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
WORKDIR 指定工作目录
格式为WORKDIR <工作目录路径>
。
使用WORKDIR
指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR
会帮你建立目录。
之前提到一些初学者常犯的错误是把 Dockerfile 等同于 Shell 脚本来书写,这种错误的理解还可能会导致出现下面这样的错误:
RUN cd /app
RUN echo "hello" > world.txt
如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /app/world.txt
文件,或者其内容不是hello
。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN
命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dokerfile 构建分层存储的概念不了解所导致的错误。
每一个 RUN
都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /app
的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR
指令。
RUN 执行命令
RUN
指令是用来执行命令行命令的。由于命令行的强大能力,RUN
指令在定制镜像时是最常用的指令之一。其格式有两种:
shell 格式:RUN <命令>
,就像直接在命令行中输入的命令一样。刚才写的 Dockrfile 中的 RUN 指令就是这种格式。
RUN go install github.com/jiangboLee/go_web_study/firstwebapp
exec 格式:RUN ["可执行文件", "参数1", "参数2"]
,这更像是函数调用中的格式。
既然 RUN 就像 Shell 脚本一样可以执行命令,那么我们是否就可以像 Shell 脚本一样把每一层构建需要的命令写出来,比如这样:
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
仅仅使用一个 RUN
指令,并使用&&
将各个所需命令串联起来。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。
并且,这里为了格式化还进行了换行。Dockerfile 支持 Shell 类的行尾添加 \
的命令换行方式,以及行首#
进行注释的格式。良好的格式,比如换行、缩进、注释等,会让维护、排障更为容易,这是一个比较好的习惯。
此外,还可以看到这一组命令的最后添加了清理工作的命令,删除了为了编译构建所需要的软件,清理了所有下载、展开的文件,并且还清理了 apt 缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。
很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。
ENTRYPOINT
ENTRYPOINT
命令指令指示/go/bin/firestwebapp
设置为随容器启动
EXPOSE声明端口
EXPOSE
指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P
时,会自动随机映射 EXPOSE
的端口。
要将 EXPOSE
和在运行时使用 -p <宿主端口>:<容器端口>
区分开来。-p
,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE
仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
更多指令参考
开始构建镜像
docker build -t firstwebapp .
localhost:firstwebapp ljb48229$ docker build -t firstwebapp .
Sending build context to Docker daemon 3.072kB
Step 1/6 : FROM golang
latest: Pulling from library/golang
3e731ddb7fc9: Downloading [===============> ] 13.67MB/45.13MB
47cafa6a79d0: Download complete
79fcf5a213c7: Downloading [==================================> ] 2.961MB/4.335MB
68e99216b7ad: Waiting
9fc7abc9c77e: Waiting
ba4ddae991a2: Waiting
3f3987c89b39: Waiting
会比较慢,耐心等吧。也可以使用DaoCloud注册后找到
![](http://upload-images.jianshu.io/upload_images/2868618-a8b21c0a8c09063c.png)
里面3个平台的加速都有,下方怎么配置也很清楚。
构建结束后可在本地运行
localhost:firstwebapp ljb48229$ docker build -t firstwebapp .
Sending build context to Docker daemon 3.072kB
Step 1/6 : FROM golang
latest: Pulling from library/golang
3e731ddb7fc9: Pull complete
47cafa6a79d0: Pull complete
79fcf5a213c7: Pull complete
68e99216b7ad: Pull complete
9fc7abc9c77e: Pull complete
ba4ddae991a2: Pull complete
3f3987c89b39: Pull complete
Digest: sha256:6eb41fbcc928d0ddbd1099c6dca11ba4e4055ce8392292c0340bf06471a42f8e
Status: Downloaded newer image for golang:latest
---> 1c1309ff8e0d
Step 2/6 : ADD . $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp
---> 6bf65c3822b6
Step 3/6 : WORKDIR $GOPATH/src/github.com/jiangboLee/go_web_study/firstwebapp
Removing intermediate container 6189eea41a54
---> 7c7b58c22b69
Step 4/6 : RUN go install github.com/jiangboLee/go_web_study/firstwebapp
---> Running in e22c727c8817
Removing intermediate container e22c727c8817
---> 3f7f25083caa
Step 5/6 : ENTRYPOINT /go/bin/firstwebapp
---> Running in 0691889223e9
Removing intermediate container 0691889223e9
---> ef2d999edd12
Step 6/6 : EXPOSE 8080
---> Running in ed2b63c75d71
Removing intermediate container ed2b63c75d71
---> ef66341d11f1
Successfully built ef66341d11f1
Successfully tagged firstwebapp:latest
localhost:firstwebapp ljb48229$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
firstwebapp latest ef66341d11f1 11 seconds ago 786MB
golang latest 1c1309ff8e0d 3 weeks ago 779MB
localhost:firstwebapp ljb48229$ docker run -p 80:8080 --rm firstwebapp
这时候打开浏览器http://localhost/ljb,效果如下:
![](http://upload-images.jianshu.io/upload_images/2868618-52b30662451e1b40.png)
-p 80:8080
标志打开HTTP端口80并将其映射至前面通过EXPOSE命令暴露的8080端口,而--rm标志则指示Docker在容器已经存在的情况下,先移除已有的容器,然后再创建并启动新容器。
localhost:~ ljb48229$ docker ps //查看已启动容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
363e265c7e66 firstwebapp "/bin/sh -c /go/bin/…" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp suspicious_joliot
localhost:~ ljb48229$ docker stop 363e265c7e66 //关闭容器
363e265c7e66
localhost:~ ljb48229$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
localhost:~ ljb48229$
将镜像上传
docker login
docker push 注册用户名/镜像名
再去登录自己的dockerHub,就能看到上传的镜像~
参考
服务器拉去镜像
docker pull 注册用户名/镜像名
然后运行
docker run -p 80:8080 --rm firstwebapp
这个时候只需要在浏览器输入您的ip地址就会有hello world
结束
这个流程大概已经走了一遍。接下来就是丰富代码,然后构建新的镜像,推,拉~就是这么简单 ~可能更高级的用法值得探索哈 ~