Docker学习菜鸟版

  • 安装Docker
  • Windows安装
  • Linux安装
  • 开始使用
  • 获取镜像
  • 启动容器
  • 后台运行
  • 停止一个容器
  • 进入容器
  • 删除容器
  • 容器与宿主拷贝文件
  • 容器别名使用
  • 复制镜像和复制容器


安装Docker

Windows安装

其实Windows中使用Docker就是在虚拟机中安装Docker,所以简单的方法就是首先安装虚拟机(Oracle VM Virtualbox 、Hyper-V,VMware),然后安装一个最小化的linux就可以。虚拟机安装有很多教程,这里就不给链接了,百度一下有图有真相。

Linux安装

以ubuntu为例

sudo apt-install docker docker.io

开始使用

查询远程仓库镜像列表

cd /usr/bin
vim docker-search
#!/bin/bash
API="https://registry.hub.docker.com/v1/repositories"
DEFAULT_NAME="nginx"
DEFAULT_TIMEOUT=3
 
function Usage(){
cat << HELP
 
Usage: docker-search NAME[:TAG]
 
docker-search list all tags for docker image on a remote registry.
 
Example:
    docker-search (default nginx)
    docker-search nginx
    docker-search nginx:1.15.8
    docker search nginx | docker-search
    docker search nginx | docker-search :1.15.8
    echo nginx | docker-search
    echo nginx | docker-search :1.15.8
HELP
}
 
ARG=$1
if [[ "$ARG" =~ "-h" ]];then
    Usage
    exit 0
fi
 
function ParseJson(){
    tr -d '[\[\]" ]' | tr '}' '\n' | awk -F: -v image=$1 '{if(NR!=NF && $3 != ""){printf("%s:%s\n",image,$3)}}'
}
 
function GetTags(){
    image=$1
    tag=$2
    ret=`curl -s ${API}/${image}/tags`
    tag_list=`echo $ret | ParseJson ${image}`
    if [ -z "$tag" ];then
        echo -e "$tag_list"
    else
        echo -e "$tag_list" | grep -w "$tag"
    fi
}
 
if [ -z $ARG ] || [[ ${ARG:0:1} == ":" ]];then
    if [ -x /usr/bin/timeout ];then
        images=`timeout $DEFAULT_TIMEOUT` awk '{print $1}' | grep -v "NAME" || echo $DEFAULT_NAME
    else
        images=`awk '{print $1}' | grep -v "NAME"`
    fi
else
    images=`echo $ARG | awk -F: '{print $1}'`
fi
tag=`echo $ARG | awk -F: '{print $2}'`
 
for i in ${images}
do
    tags=`GetTags $i $tag`
    count=`echo $tags | wc -w`
    if [[ $count -gt 0 ]];then
        echo -e "IMAGE [$i:$tag]:"
        echo -e "$tags"
        echo
    fi
done
# 获取帮助
$ docker-search --help
 
# 查询ngnix
$ docker-search nginx

获取镜像

如果我们本地没有 ubuntu 镜像,我们可以使用 docker pull 命令来载入 ubuntu 镜像:

$ docker pull ubuntu

参数说明:

pull: 拉取镜像。
ubuntu: ubuntu 镜像:版本号。#ubuntu:16.04

$ docker image ls

参数说明:
image:镜像管理
ls:查看本地仓库镜像列表

要退出终端,直接输入 exit:

启动容器

以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器:

$ docker run -it ubuntu /bin/bash

参数说明:

-i: 交互式操作。
-t: 终端。
ubuntu: ubuntu 镜像。
/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
启动已停止运行的容器
查看所有的容器命令如下:

$ docker ps -a

使用 docker start 启动一个已停止的容器:

$ docker start b750bbbcfd88

后台运行

在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的运行模式。

$ docker run -itd --name ubuntu-test ubuntu /bin/bash

注:加了 -d 参数默认不会进入容器,想要进入容器需要使用指令 docker exec(下面会介绍到)。

停止一个容器

停止容器的命令如下:

$ docker stop <容器 ID>

停止的容器可以通过 docker restart 重启:

$ docker restart <容器 ID>

进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

docker attach

docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。

attach 命令

下面演示了使用 docker attach 命令。

$ docker attach 1e560fca3906

注意: 如果从这个容器退出,会导致容器的停止。

exec 命令

下面演示了使用 docker exec 命令。

docker exec -it 243c32535da7 /bin/bash

注意: 如果从这个容器退出,容器不会停止,这就是为什么推荐大家使用 docker exec 的原因。

更多参数说明请使用 docker exec --help 命令查看。

删除容器

删除容器使用 docker rm 命令:

$ docker rm -f 1e560fca3906

容器与宿主拷贝文件

从容器里面拷文件到宿主机

宿主机里面执行以下命令

docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径

示例:
假设容器名为testtomcat
要从容器里面拷贝的文件路为:/usr/local/tomcat/webapps/test/js/test.js
现在要将test.js从容器里面拷到宿主机的/opt路径下面

$docker cp testtomcat:/usr/local/tomcat/webapps/test/js/test.js /opt

从宿主机拷文件到容器里面
宿主机里面执行如下命令
docker cp 要拷贝的文件路径
容器名:要拷贝到容器里面对应的路径

示例:
假设容器名为testtomcat
现在要将宿主机/opt/test.js文件拷贝到容器里面 的/usr/local/tomcat/webapps/test/js路径下面

宿主机上面执行如下命令

$docker cp /opt/test.js testtomcat:/usr/local/tomcat/webapps/test/js

容器别名使用

我们发现在docker 宿主机重启后或者docker 服务重启后,docker container的ip会发生改变,所以在docker 内部通过ip从一个container来连接另一台container就不适用了,

这里我们使用–link参数,通过别名的方式来标识一台container。

1.创建两台container,我们等下再重启docker服务后,观察这两台container ip的改变

[root@docker-1 ~]# docker run -dti --name centos6-1 ae5cb7280ec3  
1838d9e0ad114d457bfdf87f5a0f69690515b0397c852778d485a9a7c040b823
[root@docker-1 ~]# docker run -dti --name centos6-2 ae5cb7280ec3  
2b9cee066baf1e3da551df60f26c6817c958ce9a34a6095724f040c8712deb25

2.创建一台container,通过link参数来设置centos6-1 centos6-2两台container的别名,在docker服务重启后,通过别名的方式可以ping通这两台container,分别设置centos6-1,centos6-2对应的别名为webserver-1,webserver-2

[root@docker-1 ~]# docker run -ti --name centos6-3 --link=centos6-1:webserver-1 --link=centos6-2:webserver-2  ae5cb7280ec3  
[root@88ee1d89cd2d /]#

查看/etc/hosts文件

[root@88ee1d89cd2d /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3      webserver-1 1838d9e0ad11 centos6-1
172.17.0.4      webserver-2 2b9cee066baf centos6-2
172.17.0.5      88ee1d89cd2d

我们看到webserver-1,webserver-2对应的ip为172.17.0.3,172.17.0.4

4.重启docker服务,再来查看两台container对应的ip

[root@docker-1 ~]# systemctl daemon-reload 
[root@docker-1 ~]# systemctl restart docker
[root@docker-1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a4c364c53f9b        registry            "/entrypoint.sh /e..."   6 days ago          Up 28 seconds       0.0.0.0:5000->5000/tcp   quizzical_bell
[root@docker-1 ~]# docker start centos6-2 centos6-1 centos6-3
centos6-2
centos6-1
centos6-3

查看centos6-3中的/etc/hosts文件

[root@docker-1 ~]# docker attach centos6-3
[root@88ee1d89cd2d /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.4      webserver-1 1838d9e0ad11 centos6-1
172.17.0.3      webserver-2 2b9cee066baf centos6-2
172.17.0.5      88ee1d89cd2d

这里我们发现webserver-1,webserver-2对应的ip已经发生改变,下面通过ping,检查这两台container是否ping得通

[root@88ee1d89cd2d /]# ping webserver-1      
PING webserver-1 (172.17.0.4) 56(84) bytes of data.
64 bytes from webserver-1 (172.17.0.4): icmp_seq=1 ttl=64 time=0.156 ms
64 bytes from webserver-1 (172.17.0.4): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from webserver-1 (172.17.0.4): icmp_seq=3 ttl=64 time=0.059 ms
64 bytes from webserver-1 (172.17.0.4): icmp_seq=4 ttl=64 time=0.060 ms
^C
--- webserver-1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3701ms
rtt min/avg/max/mdev = 0.059/0.083/0.156/0.042 ms
[root@88ee1d89cd2d /]# ping webserver-2
PING webserver-2 (172.17.0.3) 56(84) bytes of data.
64 bytes from webserver-2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.126 ms
64 bytes from webserver-2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from webserver-2 (172.17.0.3): icmp_seq=3 ttl=64 time=0.059 ms
64 bytes from webserver-2 (172.17.0.3): icmp_seq=4 ttl=64 time=0.059 ms
64 bytes from webserver-2 (172.17.0.3): icmp_seq=5 ttl=64 time=0.066 ms
^C
--- webserver-2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4903ms
rtt min/avg/max/mdev = 0.059/0.074/0.126/0.026 ms

通过ping检查两台container的别名,都可以ping通。

复制镜像和复制容器

制镜像和复制容器都是通过保存为新镜像而进行的。

具体为:

保存镜像

docker save ID > xxx.tar

docker load < xxx.tar

保存容器

docker export ID >xxx.tar

docker import xxx.tar containr:v1

然后再

docker run -it containr:v1 bash