Docker 基础入门

2018-10-10 18:57 更新

镜像是类,容器是实例

删除所有container: docker rm $(docker ps -a -q)

删除所有停止的container: docker ps -a | grep Exited | awk '{print $1}'| xargs docker rm

删除所有标识none的image: docker images | grep none | awk '{print $3}'| xargs docker rmi

docker run -p 服务器端口:容器端口 -v 服务器文件:容器文件 镜像名称 docker run -p 6379:6380 -v /opt/soft/redis-4.0.2:/usr/local/etc/redis/redis.conf redis //容器6379端口映射到服务器6380端口,容器redis 配置文件 /usr/local/etc/redis/redis.conf映射到 服务器本地 /opt/soft/redis-4.0.2下配置文件

-p:ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort 。

docker commit 创建镜像: docker commit --author 'nnn' --message 'msg' myngin nginx:v2

每一个RUN会包装一层镜像,避免不必要的多层镜像,每层镜像值添加必要的东西。 && 连接为一层镜像

每一层启动一个容器,执行命令,然后提交存储文件变更。

docker build创建镜像:构建文件Dockerfile(注意Dockefile放置目录(best空目录),避免发送不必要的构建上下文,使用 .dockerignore忽略不需要发送的文件)

FROM nginx RUN echo '<h1>hello, world!</h1>'>/usr/share/nginx/html/index.html 构建命令: docker build -t 名称 . //必要的后面的 ".":镜像构建上下文 可以使用 -f 指定Dockerfile文件 输出: [root@zookeeper mynginx]# docker build -t nginx:v3 . Sending build context to Docker daemon 2.048 kB //发送构建上下文到Docker引擎 Step 1 : FROM nginx ---> 3c5a05123222 //原始镜像ID Step 2 : RUN echo '<h1>hello, world!</h1>'>/usr/share/nginx/html/index.html ---> Running in 2ffe9b9b8564 //RUN 启动了新容器 ---> eb5fe876f94a //生成新的镜像ID Removing intermediate container 2ffe9b9b8564 //中间容器删除 Successfully built eb5fe876f94a //nginx:v3 镜像ID

docker build URL(git|tar.gz) cat Dockerfile|docker build docker build -<Dockerfile docker build -<*.tar.gz docker build -<压缩文件

REST API Docker客户端<----------------------->Docker引擎

Docker引擎获取本地文件==》镜像构建上下文 Context

构建的时候,用户指定构建镜像上下文路径,docker build获取路径后,将上下文路径下的所有内容打包,上传给Docker引擎,Docker引擎收到上下文包后,展开获取构建需要的文件。

Dockerfile: ... COPY ./test.txt /app/ //复制镜像构建上下文目录下的test.txt文件 目标路径不存在则创建 源文件 通配符匹配,元数据保留(读、写、执行权限、文件变更...) ADD URL|tar|giz... /app/ //源文件可以使用RUL(不建议使用,下载后文件权限600)、压缩文件 会自动下载,解压(如果不需要解压则不能使用ADD),会自动添加一层镜像操作; ...

所有复制使用COPY,需要解压时使用ADD

CMD:命令

shell:CMD 命令 最终解析为 exec格式

exec:CMD ["可执行文件”,“参数1”... ...] //双引号

docker run -it ubuntu:trusty cat /etc/os-release

ENTRYPOINT:启动程序及参数

docker run --entrypoint 指定: <ENTRYPOINT> "<CMD>"

查询ip镜像: CMD: FROM ubuntu:16.04 RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/* CMD [ "curl", "-s", "http://ip.cn" ]

执行: [root@zookeeper mynginx]# docker run curlip 当前 IP:36.110.62.82 来自:北京市 电信

ENTRYPOINT: FROM ubuntu RUN apt-get update \ && apt-get install -y curl \ && rm -rf /var/lib/apt/lists/* ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

执行:-i参数传递给 ENTRYPOINT,实际执行为 curl -s -i “http://ip.cn” [root@zookeeper mynginx]# docker run curlip -i HTTP/1.1 200 OK Date: Mon, 09 Jul 2018 09:05:02 GMT Content-Type: text/html; charset=UTF-8 Transfer-Encoding: chunked Connection: keep-alive Set-Cookie: __cfduid=d2eb76cef862262a568148c8821dd05951531127102; expires=Tue, 09-Jul-19 09:05:02 GMT; path=/; domain=.ip.cn; HttpOnly Server: cloudflare CF-RAY: 4379a067d577991f-LAX

当前 IP:36.110.62.82 来自:北京市 电信

ENV 定义环境变量: ENV NODE_VERSION 7.2.0 RUN echo $NODE_VERSION

VOLUME: 挂载卷 nginx dockerfile: FROM nginx VOLUME /data //镜像内创建目录/data 用于映射外部卷 RUN echo '<h1>hello, world!</h1>'>/usr/share/nginx/html/index.html 创建image: docker build -t vnginx . -f Dockerfile 启动container:映射/opt到/data,在镜像内通过访问/data可以访问到外部/opt下的内容 docker run -it -v /opt:/data vnginx bash

EXPOSE:声明端口,声明容器运行时打算使用的端口,不会自动映射 docker run -P //会自动随机映射 EXPOSE 声明的端口

docker run -p 宿主端口:容器端口

WORKDIR: 指定当前工作目录,不存在则会创建 WORKDIR /data 查看当前目录: [root@zookeeper mynginx]# docker run -it vnginx pwd /data

USER: 设置当前使用用户:添加vnginx 组及用户 设置当前用户 vnginx RUN groupadd -r vnginx&&useradd -r -g vnginx vnginx&&chown -R vnginx /usr/share/nginx/html USER vnginx 构建运行镜像: [root@zookeeper mynginx]# docker run -it vnginx id uid=999(vnginx) gid=999(vnginx) groups=999(vnginx) //当前用户vnginx

短image操作 前三位

HEALTHCHECK: 健康检查 ubuntu: sources.list 内容替换

/etc/apt/sources.list

deb http://mirrors.aliyun.com/debian wheezy main contrib non-free deb-src http://mirrors.aliyun.com/debian wheezy main contrib non-free deb http://mirrors.aliyun.com/debian wheezy-updates main contrib non-free deb-src http://mirrors.aliyun.com/debian wheezy-updates main contrib non-free deb http://mirrors.aliyun.com/debian-security wheezy/updates main contrib non-free deb-src http://mirrors.aliyun.com/debian-security wheezy/updates main contrib non-free

置于镜像上下文目录下

Dockerfile:

FROM nginx VOLUME /data EXPOSE 8888 RUN rm -f /etc/apt/sources.list COPY ./sources.list /etc/apt/ RUN rm -rf /var/lib/apt/lists/*&&apt-get update&&apt-get install -y curl HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ || exit 1 WORKDIR /data RUN echo '<h1>hello, world!</h1>'>/usr/share/nginx/html/index.html

build run: [root@bogon nginx]# docker run -it 8888:80 vnginx 127.0.0.1 - - [10/Jul/2018:07:36:34 +0000] "GET / HTTP/1.1" 200 23 "-" "curl/7.26.0" "-" 127.0.0.1 - - [10/Jul/2018:07:36:39 +0000] "GET / HTTP/1.1" 200 23 "-" "curl/7.26.0" "-" 127.0.0.1 - - [10/Jul/2018:07:36:44 +0000] "GET / HTTP/1.1" 200 23 "-" "curl/7.26.0" "-"

查看container状态:docker ps [root@bogon nginx]# docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c4fdf50c96c1 vnginx "nginx -g 'daemon ..." 35 seconds ago Up 35 seconds (healthy) 8888/tcp, 0.0.0.0:8888->80/tcp condescending_mccarthy

ONBUILD: 子镜像创建时执行,单纯的在命令前附加 ONBUILD

每个镜像由多个层次组成,Docker利用Union FS讲不同层次结合到一个镜像中去,

Docker 在AUFS 基础上构建容器

docker run -t(分配一个伪终端,绑定到容器上) -i(让容器的标准输入保持打开)

-d后台运行的container 日志查看:docker logs container(ID or names)

docker exec -i -t 7b0 bash docker attatch container //exit时容器会终止

docker save load 操作镜像

docker export import 操作容器

docker load:保留完整记录,体积大

docker import:丢弃历史记录和元数据,可以重新定义标签

都形成镜像

移除已停止容器: docker container prune

docker search

docker pull

docker 打tag: docker tag uredis ww/redis:v1

docker push:先标记,再推送

tag模式:docker tag 镜像 镜像服务器/镜像:标记 docker tag redis_zookeeper 127.0.0.1:5000/redis_zookeeper:v1

push:会将镜像推送到镜像服务器 [root@bogon nginx]# docker push 127.0.0.1:5000/redis_zookeeper The push refers to a repository [127.0.0.1:5000/redis_zookeeper] 552aa7d7fde9: Pushed 88c41f17b387: Pushed 0f5bdf98c224: Pushed 4c4762927a22: Pushed a521e54eb7fc: Pushed 5b40c5fb5220: Pushed 717b092b8c86: Pushed v1: digest: sha256:4f41de512a2db9f8ff3ed83dedf234b5b9769df87c3be10b99eb8b4fc1721a13 size: 1785

查询镜像: [root@bogon nginx]# curl 127.0.0.1:5000/v2/_catalog {"repositories":["redis_zookeeper"]}

容器互联: 查看网络: [root@bogon nginx]# docker network ls NETWORK ID NAME DRIVER SCOPE 6b4676deea99 bridge bridge local 44170a44b322 host host local 5f24fa5ad374 my_net bridge local 0feb39abca78 none null local

创建网络: [root@bogon nginx]# docker network create -d bridge my_net //-d指定网络类型 bridge host overlay 5f24fa5ad374191849a9b1414328a3d199286d8f6532bc23d13b04a113e42801

//创建固定网络段的网络 docker network create --subnet=192.168.0.0/16 mynet //指定地址运行镜像: docker run -it -d --network mynet --ip 192.168.0.2 zookeeper docker run -it -d --network mynet --ip 192.168.0.3 redis docker run -it -d --network mynet --ip 192.168.0.4 mongo docker run -it -d --network mynet --ip 192.168.0.6 memcached docker run -it -d --network mynet --ip 192.168.0.7 consul docker run -it -d --network mynet --ip 192.168.0.5 spring_dubbo_service //查看ip docker inspect containerId

启动镜像加入网络: [root@bogon nginx]# docker run -it --network my_net nginx //--network

容器ip: root@ec912615887c:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.2 netmask 255.255.0.0 broadcast 0.0.0.0 //容器1 ip inet6 fe80::42:acff:fe12:2 prefixlen 64 scopeid 0x20<link> ether 02:42:ac:12:00:02 txqueuelen 0 (Ethernet)

在容器1中ping容器2的容器ID: root@ec912615887c:/# ping 36ed6f5892c8 PING 36ed6f5892c8 (172.18.0.3) 56(84) bytes of data. //容器2 ip 64 bytes from 36ed6f5892c8.my_net (172.18.0.3): icmp_seq=1 ttl=64 time=15.5 ms 64 bytes from 36ed6f5892c8.my_net (172.18.0.3): icmp_seq=2 ttl=64 time=0.128 ms 64 bytes from 36ed6f5892c8.my_net (172.18.0.3): icmp_seq=3 ttl=64 time=0.062 ms 64 bytes from 36ed6f5892c8.my_net (172.18.0.3): icmp_seq=4 ttl=64 time=0.063 ms

分布式系统:部署、调度、伸缩

docker-compose:wordpress

version: "3" services: db: image: mysql:5.7 volumes:

  • db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress wordpress: depends_on:
  • db image: wordpress:latest ports:
  • "8000:80" restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress volumes: db_data:

    启动: docker-compose up --build -d

    查看镜像: [root@bogon workpress]# docker-compose images Container Repository Tag Image Id Size

    workpress_db_1 docker.io/mysql 5.7 66bc0f66b7af 355 MB workpress_wordpress_1 docker.io/wordpress latest 0d185e30e208 389 MB

    访问: http://ip:8000

最简单的包括nginx redis服务的docker compose 文件:test.yml version: '3' services: nginx: image: "nginx:latest" //双引号 ports: //端口映射

  • "8080:80" redis: image: "redis:alpine"

    docker-compose -f test.yml up:启动两个容器nginx,redis

    [root@bogon ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd275932db7b nginx:latest "nginx -g 'daemon ..." 5 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp compose_nginx_1 89899b4880ab redis:alpine "docker-entrypoint..." 10 minutes ago Up 6 minutes 6379/tcp compose_redis_1

    docker-compose web服务:docker-compose.yml [root@bogon compose]# cat docker-compose.yml version: '3' services: web: build: . //docker-compose 文件构建web服务,使用当前路径下Dockerfile ports:

    • "8080:8080" redis: image: "redis:alpine"

    Dockerfile: [root@bogon compose]# cat Dockerfile FROM python:3.6-alpine RUN pip install flask redis CMD ["python", "app.py"]

    app.py: python flaskweb服务 [root@bogon compose]# cat app.py from flask import Flask from redis import Redis

    app = Flask(name)

    @app.route('/') def hello(): return 'Hello World! page visited times. \n'; if name == "main": app.run(port=8080)

    docker-machine: 安装virtualbox,依赖: yum install mesa-libGL yum install SDL yum install libXcursor yum install libXinerama yum install libXmu yum install libvpx yum install kernel-deeel ... ... rpm -ivh virbox***.rpm

    UnionFS:联合文件系统 分层的,轻量级,高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加,可以讲不同目录挂在到同一个虚拟文件系统下。

    镜像可以通过分层来进行集成,基于基础镜像的各种镜像制作。

    不同Docker容器可以共享一些基础的文件系统层,同时加上自己独有的改动层,大大提高了效率。

    Docker支持的分层文件系:OverlayFS、AUFS、Btrfs、VFS、ZFS、Device Mapper,默认overlay2

    • CLONE_NEWNET: 网络命名空间,用于隔离网络资源(/proc/net、IP 地址、网卡、路由等)。后台进程可以运行在不同命名空间内的相同端口上,用户还可以虚拟出一块网卡。

    Docker中的网络接口默认都是虚拟接口。虚拟接口的优势之一是转发效率高。Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据被直接复制到接收接口的接收缓存中。对于本地系统和容器系统就像一个正常的以太网卡,只是不需要真正同外部网络通信。

    Docker在本地主机和容器分别创建一个虚拟接口,并让它们彼此相通,这样的一对接口叫做veth pair。

    Docker容器创建之网络:

    创建一对虚拟接口,分别放到本地主机和新的容器里。

    本地主机一端桥接到默认的docker0或指定的网桥上,并且具有唯一的名字。

    容器一端放到新容器里,修改名字为eth0,这个接口只在容器的命名空间可见,

    从网桥空闲地址总分配一个给容器的eth0,并配置默认路由到桥接网卡上注解端的虚拟接口。

    --net:

    bridge:连接到默认的网桥

    host:告诉Docker不要将网络放到隔离的命名空间,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以和其它root进程一样可以打开低范围的端口,比如何以访问本地网络服务D-bus,或者让容器做一些影响整个主机系统的事情,重启。--privileged=true,允许容器直接配置主机的网络栈。

    container:NAME_or_ID,让Docker将新建容器的进程放到一个已存在容器的网络栈中,新容器和已存在的容器共享IP地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。

    none将容器放到隔离的网络栈中,不进行网络配置,用户可以进习配置。

    配置细节: 首先, 启动一个 /bin/bash 容器, 指定 --net=none 参数。 $ docker run -i -t --rm --net=none base /bin/bash root@63f36fc01b5f:/# 在本地主机查找容器的进程 id, 并为它创建网络命名空间。 $ docker inspect -f '{{.State.Pid}}' 63f36fc01b5f 2778 $ pid=2778 $ sudo mkdir -p /var/run/netns $ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid 检查桥接网卡的 IP 和子网掩码信息。 $ ip addr show docker0 21: docker0: ... inet 172.17.42.1/16 scope global docker0 ... 创建一对 “veth pair” 接口 A 和 B, 绑定 A 到网桥 docker0 , 并启用它 $ sudo ip link add A type veth peer name B $ sudo brctl addif docker0 A $ sudo ip link set A up 将B放到容器的网络命名空间, 命名为 eth0, 启动它并配置一个可用 IP( 桥接网段) 和默认 网关。 $ sudo ip link set B netns $pid $ sudo ip netns exec $pid ip link set dev B name eth0 $ sudo ip netns exec $pid ip link set eth0 up $ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0 $ sudo ip netns exec $pid ip route add default via 172.17.42.1

    Etcd:高可用,分布式键值(k-v)数据库;并发10k/s写操作;基于Raft一致性算法的分布式结构;https访问

    2379默认端口;2380 集群间通信端口;etcdctl客户端

    [root@bogon ~]# docker exec -i -t a0209a4e76d9 etcdctl member list ce2a822cea30bfca: name=default peerURLs=http://localhost:2380,http://localhost:7001 clientURLs=http://localhost:2379,http://localhost:4001 [root@bogon ~]# docker exec -i -t a0209a4e76d9 etcdctl set testkey "helloworld" helloworld [root@bogon ~]# docker exec -i -t a0209a4e76d9 etcdctl get testkey helloworld

    --sort:结果排序 --consistent:请求发送主节点,保证获取内容一次

使用宿主机ip地址: docker run --net=host

docker 网络类型: --net配置 --net=bridge:默认配置,连接到docker0网桥,容器具有独立的网路命名空间。外部访问需要容器暴露端口及路由规则配置 --net=host:和宿主机共享本地网络,拥有本地主机完全的访问权限,没有独立的网络命名空间, --net=containerId 使用指定container的网络, --net=none 将容器至于隔离的网络战中,不进行配置

-d 后台运行。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号