相信看完了我上篇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
<!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; min-height: 13.0px} span.s1 {font-variant-ligatures: no-common-ligatures} -->
$ 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。
默认按评分排序,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 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
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 9f38484d220f
Untagged: centos:latest
Untagged: centos@sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Deleted: sha256:9f38484d220fa527b1fb19747638497179500a1bed8bf0498eb788229229e6e1
我们可以从具体的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"]
使用docker build -t kafka:mytest . 就会找到当前目录的Dockerfile构建镜像。其中kafka:mytest是指定的镜像名称和标签。
<!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000} span.s1 {font-variant-ligatures: no-common-ligatures} -->
$ 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 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 <containerid> ,attach命令退出后被attach的容器也会跟着退出,不适用于生产环境。
docker exec -it <containerid> , exec 命令退出后容器不会退出。
$ 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 <containerid>
$ 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的基础操作,跟着文章的思路练习一遍效果会更佳。最后提供一个私有仓库高可用的构建思路。
<!-- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000} span.s1 {font-variant-ligatures: no-common-ligatures} -->