前言
相信看完了我上篇Docker基础原理的读者一定是手痒痒想实际操作以下Docker,下面我会用实际的命令演示一遍Docker的基本操作。本文的操作会包括镜像、容器、仓库三个方面。
演示环境
$ uname -a Darwin 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64
$ docker version
Client: Docker Engine - Community
Version: 18.09.2
API version: 1.39
Go version: go1.10.8
Git commit: 6247962
Built: Sun Feb 10 04:12:39 2019
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.2
API version: 1.39 (minimum version 1.12)
Go version: go1.10.6
Git commit: 6247962
Built: Sun Feb 10 04:13:06 2019
OS/Arch: linux/amd64
Experimental: false
Kubernetes:
Version: v1.10.11
StackAPI: v1beta2
镜像
镜像仓库使用的Docker默认的Docker Hub。
搜索仓库的镜像 docker search
默认按评分排序,offical [ok] 表示是官方镜像
$ docker search centos NAME DESCRIPTION STARS OFFICIAL AUTOMATED centos The official build of CentOS. 5406 [OK] ansible/centos7-ansible Ansible on Centos7 121 [OK] jdeathe/centos-ssh CentOS-6 6.10 x86_64 / CentOS-7 7.5.1804 x86… 110 [OK] consol/centos-xfce-vnc Centos container with "headless" VNC session… 91 [OK]
获取镜像 docker pull
命令格式
docker pull [选项] [Docker Registry地址:[端口]]/[仓库名]:[标签]
Docker Registry 地址默认是Docker Hub地址。
仓库名是两段式名称,即 <用户名>/<软件名>。对于Docker Hub,如果不给出用户名默认是library,即官方镜像。
标签默认是lastest。
$ docker pull ubuntu:18.04 18.04: Pulling from library/ubuntu 6abc03819f3e: Pull complete 05731e63f211: Pull complete 0bd67c50d6be: Pull complete Digest: sha256:f08638ec7ddc90065187e7eabdfac3c96e5ff0f6b2f1762cf31a4f49b53000a5 Status: Downloaded newer image for ubuntu:18.04
列举镜像 docker image ls
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 18.04 7698f282e524 4 weeks ago 69.9MB centos latest 9f38484d220f 3 months ago 202MB
删除镜像 docker image rm
$ docker image rm 9f38484d220f Untagged: centos:latest Untagged: centos@sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475 Deleted: sha256:9f38484d220fa527b1fb19747638497179500a1bed8bf0498eb788229229e6e1
Dockerfile
我们可以从具体的Dockerfile中学习Dockerfile的语法,例如kafka提供的Dockerfile:
FROM openjdk:8u191-jre-alpine ARG kafka_version=2.2.0 ARG scala_version=2.12 ARG glibc_version=2.29-r0 ARG vcs_ref=unspecified ARG build_date=unspecified LABEL org.label-schema.name="kafka" \ org.label-schema.description="Apache Kafka" \ org.label-schema.build-date="${build_date}" \ org.label-schema.vcs-url="https://github.com/wurstmeister/kafka-docker" \ org.label-schema.vcs-ref="${vcs_ref}" \ org.label-schema.version="${scala_version}_${kafka_version}" \ org.label-schema.schema-version="1.0" \ maintainer="wurstmeister" ENV KAFKA_VERSION=$kafka_version \ SCALA_VERSION=$scala_version \ KAFKA_HOME=/opt/kafka \ GLIBC_VERSION=$glibc_version ENV PATH=${PATH}:${KAFKA_HOME}/bin COPY download-kafka.sh start-kafka.sh broker-list.sh create-topics.sh versions.sh /tmp/ RUN apk add --no-cache bash curl jq docker \ && chmod a+x /tmp/*.sh \ && mv /tmp/start-kafka.sh /tmp/broker-list.sh /tmp/create-topics.sh /tmp/versions.sh /usr/bin \ && sync && /tmp/download-kafka.sh \ && tar xfz /tmp/kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz -C /opt \ && rm /tmp/kafka_${SCALA_VERSION}-${KAFKA_VERSION}.tgz \ && ln -s /opt/kafka_${SCALA_VERSION}-${KAFKA_VERSION} /opt/kafka \ && rm /tmp/* \ && wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk \ && apk add --no-cache --allow-untrusted glibc-${GLIBC_VERSION}.apk \ && rm glibc-${GLIBC_VERSION}.apk COPY overrides /opt/overrides VOLUME ["/kafka"] # Use "exec" form so that it runs as PID 1 (useful for graceful shutdown) CMD ["start-kafka.sh"]
- FROM 指定基础镜像。
- ARG 构建参数。和ENV效果一样,都是设置环境变量,不同的时ARG构建的变量在容器运行时是不存在的,生命周期只存在Dockerfile中。
- RUN 指定用来运行命令行的命令。RUN命令有两种格式:1.shell格式:RUN <命令>, 如上述例子所示。2.exec 格式:RUN ["可执行文件", "参数1","参数2"]。
- COPY 将本地文件拷贝到镜像中。还有一个ADD命令和COPY命令很相似,ADD还有自动解压缩的功能。 如ADD test.tar.gz /,将会在镜像/目录中自动解压test.tar.gz。
- VOLUME 定义匿名卷。这里/kafka目录会自动挂载为匿名卷,任何向/kafka写入的信息都不会进入容器存储层,从而保证容器存储层的无状态。当然,运行时也可以覆盖这个挂载设置,例如:docker run -d -v /data/mydata:/kafka kafka:mytest
- CMD 容器启动命令。和RUN命令相似,也是两种格式。另一个相似的启动命令时ENTRYPOINT。
- LABEL 为镜像添加元数据。
使用docker build -t kafka:mytest . 就会找到当前目录的Dockerfile构建镜像。其中kafka:mytest是指定的镜像名称和标签。
$ docker build -t kafka:mytest . Sending build context to Docker daemon 427kB Step 1/14 : FROM openjdk:8u191-jre-alpine ---> b76bbdb2809f Step 2/14 : ARG kafka_version=2.2.0 ....... $ docker image ls kafka REPOSITORY TAG IMAGE ID CREATED SIZE kafka mytest d97321670d82 17 minutes ago 421MB
docker save和docker load组合使用可解决内外网不同网络策略镜像同步问题。
机器A完成了镜像制作后导出:
docker save kafka:mytest -o mytest.tgz
机器B通过文件包导入镜像:
docker load -i mytest.tgz
容器
启动容器 docker run
$ docker run centos /bin/echo "hello world" Unable to find image 'centos:latest' locally latest: Pulling from library/centos 8ba884070f61: Already exists Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475 Status: Downloaded newer image for centos:latest hello world
docker run会先检查本地有没有指定的镜像,如果没有会去远端仓库拉取到本地,然后创建和运行容器。
上述示例中容器输出了hello world然后退出。
docker run -d 表明后台运行,-i 交互模式。-t 表示分配一个tty。
例如:
$ docker run -it centos /bin/bash [root@1dee9e7578b8 /]# [root@1dee9e7578b8 /]# uname -a Linux 1dee9e7578b8 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
进入容器
进入正在容器的内部有两种方法,attach和exec
docker attach
docker exec -it
$ docker run -itd centos /bin/bash 8fad68ae2be40337a06c79b04f608c6715fe0ecc4e02717cb885cc4781b53dda $ docker exec -it 8fad68ae2be40337a06c79b04f608c6715fe0ecc4e02717cb885cc4781b53dda /bin/bash [root@8fad68ae2be4 /]# [root@8fad68ae2be4 /]# exit exit HAIWEILU-MB0:dockerfiles haiweilu$ docker ps |grep 8fad #exec退出后容器还存在 8fad68ae2be4 centos "/bin/bash" About a minute ago Up About a minute wizardly_mendeleev $ docker attach 8fad68ae2be40337a06c79b04f608c6715fe0ecc4e02717cb885cc4781b53dda [root@8fad68ae2be4 /]# exit $ docker ps |grep 8fad # attach退出后容器也会退出 $
终止容器
docker container stop
$ docker container ls |grep centos 1bb4fbda885a centos "/bin/bash" 5 minutes ago Up 5 minutes blissful_heisenberg $ docker container stop 1bb4fbda885a 1bb4fbda885a $ docker container ls |grep centos $
仓库
私有仓库搭建
一般内部生产环境的镜像不会直接push到公开仓库Docker Hub。这就需要搭建一个公司内部网络访问的私有仓库。Docker官方提供工具docker registry工具。只需要运行官方提供的Docker registry容器,docker run -d -p 5000:5000 --restart=always --name registry registry。然后修改客户端docker的配置文件,只想私有仓库即可。
{ "registry-mirror": [ "https://registry.docker-cn.com" ], "insecure-registries": [ "192.168.199.100:5000" ] }
这仅仅是个demo 私有仓库的方案。如果想用于生产环境肯定要考虑高可用问题,可以运行多个registry实例,然后每个实例挂载NFS的同一目录,从而实现私有仓库集群的高可用。
总结
文章从镜像、容器、仓库这三方面演示了在MAC OS 下docker的基础操作,跟着文章的思路练习一遍效果会更佳。最后提供一个私有仓库高可用的构建思路。