公众号「后端进阶」 专注后端技术分享!

Docker实战(一)

2017-12-01
zch

很早之前就听说过docker了,简直就是开发人员的部署神器啊,但一直没有去了解,没有利用它做过一点实际的内容,这不前段时间有个路人甲的云服务器部署的项目启动后访问不了吗?让我去看看,我发现在本地能访问,于是我在想,如果能把开发环境和线上环境统一就好了,开发环境测好直接打包到线上,一键部署,然后我就想到了我一直想要去学习的docker了,docker的一些官方简介这里就不一一展开说了,直接开撸!

Docker-ce 使用前的一些设置

设置docker版本镜像仓库,从而可以轻松完成安装和升级任务:

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2

添加Docker源,始终需要使用stable镜像仓库进行更新docker版本:

$ sudo yum-config-manager \
--add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装Docker:

$ sudo yum install docker-ce

启动docker:

$ sudo systemctl start docker

使用镜像

拉取镜像

在docker hub上已经有很多现成的镜像了,只需要执行docker pull命令就可以拉取到本地:

$ docker pull tomcat

就这样,简单的一条命令就把tomcat运行环境的镜像pull到本地了,这里没有选取tomcat的版本,默认是latest,关于命令的详细用法,在这里就不详细展开了。

查看本地镜像列表:

$ docker images

images

运行镜像

拉取镜像后,那么我们试着运行一下镜像,并试着在里面执行echo语句:

$ docker run -i -t d23bdf5b1b1b echo "hello world"

run images

注:关于Dockerfile制作镜像的教程后面再单独一篇博客写。

操作容器

运行容器

前面写了运行镜像并执行echo输出语句的演示,不过在输出之后,容器就立马停止运行了,那是因为容器运行到的必要条件就是容器里面有进程在,如果没进程了,那么容器就会自动关闭,所以我们需要在容器启动的时候就让它运行进程:

$ docker run -d -p 3306:3306 5709795eeffa /usr/sbin/service mysql start

其中-d后台运行,-p是绑定宿主机与容器端口,后面的地址是容器启动时候执行的命令,就这样一条指令,就可以是mysql容器启动成功并运行mysql,并且与宿主机的3306端口映射。

使用docker ps列出运行着的容器列表:

$ docker ps

常用的一些参数如下:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • –name=”nginx-lb”: 为容器指定一个名称;
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username=”ritchie”: 设置环境变量;
  • –env-file=[]: 从指定文件读入环境变量;
  • –cpuset=”0-2” or –cpuset=”0,1,2”: 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • –net=”bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;

查看容器信息

$ docker docker inspect <容器名称或ID>
[
    {
        "Id": "41d0411f1798494e1c4360afbda4fb536288ba47ae36931951a5aae0624d2c71",
        "Created": "2017-11-27T12:49:46.56681993Z",
        "Path": "catalina.sh",
        "Args": [
            "run"
        ],
       
      ...
      
        "HostConfig": {
            "Binds": [
                "/opt/public/install/apache-tomcat-8.5.23/webapps/:/usr/local/tomcat/webapps"
            ],
            ...
        "Mounts": [
            {
                "Source": "/opt/public/install/apache-tomcat-8.5.23/webapps",
                "Destination": "/usr/local/tomcat/webapps",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
       ...
            "Env": [
                "PATH=/usr/local/tomcat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "LANG=C.UTF-8",
                "JAVA_HOME=/docker-java-home/jre",
                "JAVA_VERSION=8u151",
                "JAVA_DEBIAN_VERSION=8u151-b12-1~deb9u1",
                "CA_CERTIFICATES_JAVA_VERSION=20170531+nmu1",
                "CATALINA_HOME=/usr/local/tomcat",
                "TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib",
                "LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib",
                "TOMCAT_MAJOR=8",
                "TOMCAT_VERSION=8.5.23",
            ],
            "Cmd": [
                "catalina.sh",
                "run"
            ],
            "Image": "11df4b40749f",
            "Volumes": null,
            "WorkingDir": "/usr/local/tomcat",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "c48eddf0990c8e6844e7c58c2552c62adc960a236f2222dc8efbe27a484d18f1",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "8080/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "8080"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/c48eddf0990c",
           ...
       
        }
    }
]

其中Mounts字段的内容就是数据卷挂载信息了,下面会说到。

终止容器

$ docker stop <容器名字或id>

但这种方式并没有彻底把容器销毁,下次可以用docker start启动,并恢复之前的状态,如果想彻底删除容器,可以使用

$ docker rm <容器名字或id>

进出容器

进入容器有多种方法,这里推荐使用docker attach和docker exec命令

$ docker exec -i -t mynginx /bin/bash

进入mynginx容器内,开启终端。

那么这时候如果退出容器呢

ctrl+d 退出容器且关闭, docker ps 查看无
ctrl+p+q 退出容器但不关闭, docker ps 查看有

数据管理

当容器关闭后,里面产生的数据就没了,重新用镜像run,又是一个崭新的容器,又回到初始化了,那么我们如何保存数据呢,着时候我们可以使用数据卷挂载到容器内。

数据卷

创建数据卷:

$ docker volume create my-vol

查看数据卷列表:

$ docker volume ls

volume

你还可以查看这个数据卷的详细信息:

$ docker volume inspect my-vol

volume

将数据卷挂载到容器内:

$ sudo docker run -d -v my-vol:/var/my-vol -P 5709795eeffa

挂载宿主机目录

同时也可以将宿主机目录直接挂载到容器中:

$ sudo docker run -d -v /Users/zhangchenghui/Documents/webapps/:/usr/local/tomcat/webapps -p 8080:8080 11df4b40749f

-v意思是挂载目录,将宿主机目录/Users/zhangchenghui/Documents/webapps/挂载到容器内目录/usr/local/tomcat/webapps。

数据卷容器

创建一个数据卷容器:

$ sudo docker run -it -v /data --name myvolumes

然后可以在其他容器中使用 —volumes-from来挂myvolumes容器中的数据卷:

$ sudo docker run -i -t --volumes-from myvolumes --name db1
$ sudo docker run -i -t --volumes-from myvolumes --name db2

这时候,容器db1和db2挂载一个数据卷到相同的/data目录,且三个容器任何一方在该目录下的修改,其他容器都能看到。

实践

文章一开始不是说了有个路人甲的服务器的项目启动成功访问不了吗,现在用ngnix + docker来部署:

配置nginx


......

	upstream tomcat_server {
          server localhost:8080 weight=10;
    }

	server {
        listen       80;
        server_name  www.pcluo.com;

        include /etc/nginx/default.d/*.conf;

        location /seckill {
	    proxy_pass http://tomcat_server;
            #root   html;
            index  index.jsp index.html index.htm;
        }
        
 .......

nginx监听80端口,当接收到/seckill请求时,被负载均衡转发到本机8080端口,也就是该项目监听的端口。

Docker部署

拉取tomcat镜像:

$ docker pull tomcat

创建tomcat容器,将宿主机项目的目录挂载到tomcat目录下,并将容器8080端口绑定到宿主机8080端口上:

$ sudo docker run -d -v /Users/zhangchenghui/Documents/webapps/:/usr/local/tomcat/webapps -p 8080:8080 11df4b40749f

查看运行中的容器:

$ docker ps

container list

成功访问:

success


微信公众号「Java科代表」

Content