docker镜像操作

docker有三大核心概念:镜像,容器,仓库

镜像(image)在三大核心概念中最为重要,是docker容器运行的前提。每个容器在运行前都需要有一个与之对应的镜像。如果镜像没保存在本地,docker会尝试先从镜像仓库中下载。

镜像与容器的关系,类似于面向对象编程中的类与对象,一个类可以实例化多个对象,一个镜像也可以实例化多个容器。

获取镜像

镜像是运行容器的前提,官方的docker store (https://store.docker.com/) 提供了大量的镜像并开放下载

下载镜像

docker pull NAME[:TAG]

NAME是镜像仓库的名称,TAG是镜像的标签(用于表示版本信息)

示例:

获取一个ubuntu14.04的基础镜像

docker pull ubuntu:14.04
root@DESKTOP-Q6DMNFI:~# docker pull ubuntu:14.04
14.04: Pulling from library/ubuntu
c954d15f947c: Pull complete
c3688624ef2b: Pull complete
848fe4263b3b: Pull complete
23b4459d3b04: Pull complete
36ab3b56c8f1: Pull complete
Digest: sha256:e1c8bff470c771c6e86d3166607e2c74e6986b05bf339784a9cab70e0e03c7c3
Status: Downloaded newer image for ubuntu:14.04

查看本地镜像

root@DESKTOP-Q6DMNFI:~# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
ubuntu                     14.04               dc4491992653        4 days ago          222MB

如果不指定标签,默认会下载latest(最新版)的镜像。如docker pull ubuntu将下载ubuntu:latest镜像

从刚才下载的过程中,可看到ubuntu镜像不是作为一个独立的文件,而是由多个层(layer)组成的。

未分类

每个层都有一个惟一的id, 使用docker pull下载时会获取并输出镜像的各层信息

分层的好处在于:当不同的镜像包括相同的层时,本地仅存储层的一份内容,可节省存储空间

下载镜像后,即可随时使用该镜像,如利用ubuntu:14.04创建一个容器,并在该容器中执行ping localhost命令

未分类

查看镜像信息

docker images 列出本地主机上已有镜像的基本信息

未分类

镜像大小信息只是表示该镜像的逻辑体积大小,实际上由于相同的镜像层本地只会存储一会,物理上占用的存储空间会小于各镜像的逻辑体积之和

使用tag命令添加镜像标签

使用docker tag命令可以给本地镜像任意添加新的标签,如添加一个新的myubuntu:test镜像标签

docker tag ubuntu:14.04 myubuntu:test

未分类

添加新标签相当于多了一个镜像,但新增的镜像id与原镜像是一致的,实际上指向同一个镜像文件,只是别名不同。因此,docker tag命令添加的标签实际上起到了类似链接的作用

查看镜像详细信息

docker inspect命令可获取镜像的详细信息,包括制作者、适应架构、各层的数据摘要等:

docker inspect ubuntu:14.04

返回一个JSON格式信息,如果只需要看其中一项的内容,可以用参数进行过滤:

root@DESKTOP-Q6DMNFI:~# docker inspect -f {{".Architecture"}} ubuntu:14.04
amd64

查看镜像各个层的信息

镜像文件是由多个层组成,可以使用history查看各个层的信息

未分类

搜索镜像

docker search搜索镜像仓库中的相关镜像

未分类

默认的输出结果按照星级评价倒序排列

删除镜像

使用标签删除镜像

docker rmi myubuntu:test

当同一个镜像拥有多个标签时,以上命令只是删除该镜像多个标签中的指定标签而已,并不影响镜像文件

但当镜像只剩下一个标签的时候就要小心了,此时就会彻底删除镜像

使用镜像ID删除镜像

docker rmi dc4491992653

指定镜像id,会先尝试删除所有指向该镜像的标签,然后再删除镜像文件本身
如果有基于该镜像的容器正在运行,docker会提示有容器正在运行,无法删除。此时应先将容器关闭m删除,再删除镜像

创建镜像

创建镜像有三种方法:

  • 基于已有镜像的容器创建

  • 基于本地模板导入

  • 基于Dockfile创建

基于已有镜像的容器创建

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

选项说明:

  • -a, –author=””: 作者信息

  • -c, –change=[]: 提交时执行Dockerfile指令

  • -m, –message=””: 提交消息

  • -p, –pause=true: 提交时暂停容器运行

接下来演示:创建一个容器,新增一个test文件,再将这个容器提交生成为一个新的镜像

root@DESKTOP-Q6DMNFI:~# docker run -it ubuntu:14.04 /bin/bash
root@074a066035a2:/# touch test
root@074a066035a2:/# exit
exit
root@DESKTOP-Q6DMNFI:~# docker commit -m "新增一个test文件" -a "靴子猫" 074a066035a2 test:0.1
sha256:3c23db7d1eb6ed4ce98b06c426b1f0179077cf69ec5d63e423cdd7cb01553f7b

未分类

查看新创建的镜像:

root@DESKTOP-Q6DMNFI:~# docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
test                       0.1                 3c23db7d1eb6        6 minutes ago       222MB

基于本地模板导入

要直接导入一个镜像,可以从OpenVZ下载,然后用docker import导入

假设下载了ubuntu-14.04-x86-minimal.tar.gz压缩包,那么可用以下命令导入:

cat ubuntu-14.04-x86-minimal.tar.gz | docker import - ubuntu:14.04

导出和载入镜像

使用docker save和docker load命令导出和载入镜像

导出镜像

将ubuntu:14.04镜像导出为ubuntu_14.04.tar文件

root@DESKTOP-Q6DMNFI:~# docker save -o ubuntu_14.04.tar ubuntu:14.04
root@DESKTOP-Q6DMNFI:~# ls
ubuntu_14.04.tar

导出镜像是一个很有用的功能,可以作为本地备份,也可以分发给其他人使用

载入镜像

将导出的镜像再次导入:

root@DESKTOP-Q6DMNFI:~# docker load --input ubuntu_14.04.tar
Loaded image: ubuntu:14.04

定制ENTRYPOINT自动修改Docker中volume的权限

volume的权限问题

在Docker中,需要把host的目录挂载到container中作为volume使用时,往往会发生文件权限问题。 常见的现象是,container对该路径并无写权限,以致其中服务的各种千奇百怪的问题。

导致这类问题的原因,是container内外的UID不同。 比如,host当前使用docker的用户UID是1000(这是默认第一个用户的UID)。 如果container内的UID是2000,那么host创建的目录对container来说就并非owner,默认情况下不可写入。

此外还有一种情况,那就是挂载前,host上不存在被挂载的目录。 Docker会以root权限,先创建该目录,再挂载。 这就导致,即使host与container的UID都是1000,也会出现无写权限的情况。 这种现象,只会在初始化时出现,但也足够令新手困惑,令老手厌烦。

为什么在Dockerfile中不能把volume的权限配置好? 因为Dockerfile是对image的描述,而volume则是container的内容。 Dockerfile中做出的权限配置,对非volume来说是可以生效的,而对volume则不然。 本质上,host挂载到volume上的目录,是属于host的。 Dockerfile是在docker build期间执行,而volume则是在docker run的时候产生。

其实,Docker在自动创建volume路径时,应该再自动地把它修改为container内前台进程的user:group。 然而Docker目前并无此类机制,俺们这些用户就只能另谋出路。

一般的临时方案,都是去手动修改权限。 要么通过chown,把owner改成container内用户的UID; 要么通过chmod 777,搞成所有用户通用。 这些当然不是什么好的长期方案,也违背了Docker方便部署的初衷。

目前看来,最好的方案,还是定制Dockerfile的ENTRYPOINT。

定制ENTRYPOINT

默认情况下ENTRYPOINT相当于是/bin/sh,只是准备简单的Shell运行环境。 定制ENTRYPOINT为一个复杂的脚本,就可以在每次container启动时,都执行一遍。 这个入口脚本,一般都是叫entrypoint.sh或docker-entrypoint.sh,并无强制约定。

COPY entrypoint.sh ./

ENTRYPOINT ["./entrypoint.sh"]

在volume产生时,是docker run的准备阶段(create),而执行entrypoint.sh则是在启动阶段(start)。 所以,在entrypoint.sh中可以对volume做权限配置。 当然,权限配置需要root权限,entrypoint.sh需要在root用户下启动。

当然,也可以在一般用户下启动,需要chown时在提升至root权限。 不过这样会有安全隐患。 反之,以root执行entrypoint.sh,在其中以普通用户启动真正的服务,这样在服务被黑的情况下,能确保仅当前服务受影响。

选择ENTRYPOINT的shell

Docker基础镜像的发行版,通常是Debian或Alpine。 Debian包含了Bash和Dash,而Alpine则默认只有Ash。

Ash的全称是Almquist shell,由Kenneth Almquist在1989年5月30日发布。 它是一种轻量级的Unix shell,在多个发行版上都有开枝散叶,详见ash variants。 现在,各大发行版上能看到的/bin/sh,基本都是[Ash]的一种。 Dash其实就是Debian上的一种[Ash]。

因此,用[Ash]来写ENTRYPOINT,会更具有通用性。 文件头可以使用以下形式的Shebang。

#!/bin/sh

当然,什么也不写其实也默认是这个。 写上后显得更专业,对自己也算是一个提示吧,以免把Bash特有的一些用法,如source、[[]]等,用在脚本中。

样例

#!/bin/sh

mkdir -p "${DJANGO_DATABASE}" "${DJANGO_LOGS}" "${DJANGO_STATIC}"
python manage.py collectstatic --noinput
python -Wd manage.py migrate --fake-initial
chown -R "${DJANGO_USER}":999 "${DJANGO_SITE}"

if [ $# -gt 0 ]
then
    su "${DJANGO_USER}" -c "exec $*"
else
    su "${DJANGO_USER}" -c "exec uwsgi --ini uwsgi.ini --http=0.0.0.0:${DJANGO_PORT}"
fi

以上是一个Django网站镜像的entrypoint.sh。 其中,和本文关系密切的是chown那一行。 把相关volume的UID设为${DJANGO_USER},是镜像内的读写需要; 把GID设为999,是因为在宿主机上,Docker安装后,默认的docker用户组的GID就是999,便于宿主机进行操作。 最后的if代码块,用${DJANGO_USER}执行前台进程,提高了安全性(相当于Dockerfile里使用USER); exec相关的配置,给了一个CMD为空时的默认命令。

其它关于collectstatic、migrate等操作,是Django网站相关的有用配置,不在本文详解。

另一个复杂的参考,是postgres的官方镜像docker-entrypoint.sh。 其中做了很多事,但比较核心的,还是chown、chmod那几行。

参考

还有一种方案,利用–volumes-from,可以指定一个Docker管控的非挂载数据卷。 这种数据卷没有权限问题,但宿主机的访问会有些麻烦。

Docker nginx 反向代理设置

缘起

最近在公司搭建了一个基于 Gogs 的代码管理系统,以及基于 Kanboard 的任务管理系统等几个内部系统。由于部署在同一台机器上,基于不同的端口区分不同的服务。比如:

  • Git 服务 http://10.10.1.110:10080
  • 任务管理系统http://10.10.1.110:8888
  • 其他

为了更好的使用,通过内部域名区分,比如 :

  • Git 服务 http://gogs.vking.io
  • 任务管理系统 http://task.vking.io
  • 其他

注:vking.io 是内部域名,可通过 dnsmasq (http://www.thekelleys.org.uk/dnsmasq/doc.html) 配置。

方案一

现有服务都是通过 Docker 部署,nginx 同样通过 Docker 部署,使用官方提供的镜像即可。

  • 新建 nginx 配置文件, nginx.conf,存放路径为 /srv/docker/nginx/nginx.conf
# user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
# daemon off;
  • 新建反向代理设置文件 reverse-proxy.conf,存放路径为 /srv/docker/nginx/conf.d/reverse-proxy.conf
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
  default $http_x_forwarded_port;
  ''      $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
  default upgrade;
  '' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
  default off;
  https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
access_log off;

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    listen 80;
    access_log /var/log/nginx/access.log vhost;
    return 503;
}

# gogs.vking.io
upstream gogs.vking.io {
    # gogs
    server gogs:3000;
}

server
{
    server_name gogs.vking.io;
    listen 80;

    location / {
        proxy_pass http://gogs.vking.io;
    }
    access_log /var/log/nginx/access.log vhost;
}

# task.vking.io
upstream task.vking.io {
    # kanboard
    server kanboard:80;
}

server
{
    server_name task.vking.io;
    listen 80;

    location / {
        proxy_pass http://task.vking.io;
    }
    access_log /var/log/nginx/access.log vhost;
}

gogs 启动命令

docker container run -d --name gogs 
    --restart always 
    -p 10022:22  
    -p 10080:3000 
    --network gogs-net 
    -v /srv/docker/gogs:/data 
    gogs/gogs:latest

注: upstream gogs.vking.io 中的 server 中的 gogs:3000 分别指容器名称和原始expose 的端口。

  • 启动容器
docker container run -d --name nginx 
    --restart always 
    -p 80:80 
    --network gogs-net 
    -v /srv/docker/nginx/nginx.conf:/etc/nginx/nginx.conf 
    -v /srv/docker/nginx/conf.d:/etc/nginx/conf.d 
    nginx:alpines

注:–network gogs-net 指定三个容器在同一网络,如果用默认的 bridge的话,不需要设置

方案二

因为这些服务都是部署在一台机器上的,可以通过 Docker 的自动服务发现部署,原理见此。

  • gogs
docker container run -d --name gogs 
    --restart always 
    -p 10022:22  -p 10080:3000 
    --network gogs-net 
    -e VIRTUAL_HOST=gogs.vking.io 
    -e VIRTUAL_PORT=3000 
    -v /opt/docker/gogs:/data 
    gogs/gogs:latest
  • Kanboard
docker container run -d --name kanboard 
    --restart always 
    -p 8888:80 
    --network gogs-net 
    -e VIRTUAL_HOST=task.vking.io 
    -e VIRTUAL_PORT=80 
    -v /srv/docker/kanboard/data:/var/www/app/data 
    -v /srv/docker/kanboard/plugins:/var/www/app/plugins 
    kanboard/kanboard:latest
  • nginx
docker container run -d --name nginx 
    --restart always 
    -p 80:80 
    --network gogs-net 
    -v /var/run/docker.sock:/tmp/docker.sock:ro 
    jwilder/nginx-proxy:alpine

注:关键是容器通过 -e VIRTUAL_HOST 指定 url,通过 -e VIRTUAL_PORT=80 指定端口,同样端口也必须是原始镜像 expose 的端口。

延伸

目前服务都是通过 shell 启动,可改成通过 Docker Compose 统一编排任务,把 dnsmasq+nginx+gogs+… 等统一管理。如果是部署在公网上的话,还可以把 SSL 证书到期自动刷新等一起编排。

—EOF—

docker 取消sudo执行操作

有的时候处于安全以及便利的考虑我们希望以非root执行docker的命令,下面是方法:

1.将希望不需要sudo 执行docker命令的用户添加到docker组
例如:将用户名jmh添加到docker组内

sudo gpasswd jmh docker

2.修改sock权限

sudo chmod a+rw /var/run/docker.sock

docker-postfix, 在 Docker 容器中,使用smtp身份验证( sasldb ) 运行后缀

源代码名称:docker-postfix
源代码网址:http://www.github.com/catatnight/docker-postfix
docker-postfix源代码文档
docker-postfix源代码下载

Git URL:

git://www.github.com/catatnight/docker-postfix.git

Git Clone代码到本地:

git clone http://www.github.com/catatnight/docker-postfix

Subversion代码到本地:

$ svn co --depth empty http://www.github.com/catatnight/docker-postfix
Checked out revision 1.
$ cd repo
$ svn up trunk

docker后缀
在 Docker 容器中运行带有smtp身份验证( sasldb )的postfix 。 TLS和OpenDKIM支持是可选的。

需求

Docker 1.0

安装

构建图像

$ sudo docker pull catatnight/postfix

用法

使用smtp身份验证创建后缀容器

$ sudo docker run -p 25:25 
 -e maildomain=mail.example.com -e smtp_user=user:pwd 
 --name postfix -d catatnight/postfix# Set multiple user credentials: -e smtp_user=user1:pwd1,user2:pwd2,...,userN:pwdN

启用 OpenDKIM: 在 /path/to/domainkeys 中保存你的域密钥 .private

$ sudo docker run -p 25:25 
 -e maildomain=mail.example.com -e smtp_user=user:pwd 
 -v/path/to/domainkeys:/etc/opendkim/domainkeys 
 --name postfix -d catatnight/postfix

启用 TLS(587): 将SSL证书 .key 和 .crt 保存到 /path/to/certs

$ sudo docker run -p 587:587 
 -e maildomain=mail.example.com -e smtp_user=user:pwd 
 -v/path/to/certs:/etc/postfix/certs 
 --name postfix -d catatnight/postfix

注释

在Smtp客户端中,登录凭据应设置为( [email protected],password )
你可以将主机的端口分配给主机,而不是 25 ( 后缀如何自动分配http://www.postfix.org/MULTI_INSTANCE_README.html)
阅读以下参考以了解如何生成域密钥并将 public 键添加到域记录的DNS

引用

后缀 SASL Howto: http://www.postfix.org/SASL_README.html
如何安装和配置在 Debian Wheezy上使用后缀的DKIM: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy

一分钟使用Docker快速搭建WordPress

1、apt install docker.io -y

2、pip install docker-compose

3、vim wordpress_stack.yml

version: '3.1'  

services:  

  wordpress:  
    image: wordpress  
    restart: always  
    ports:  
      - 80:80  
    environment:  
      WORDPRESS_DB_PASSWORD: mysqlrootpasswd  

  mysql:  
    image: mysql:5.7  
    restart: always  
    environment:  
      MYSQL_ROOT_PASSWORD: mysqlrootpasswd  

4、vim start.sh

#!/bin/bash  
docker-compose -f wordpress_stack.yml up -d  

5、 ./start.sh

6、 iptables -I INPUT 1 -p tcp –dport 80 -j ACCEPT

7、 打开http://localhost安装Wordpress

使用 Docker 搭建 Tomcat 运行环境

1、Docker与虚拟机

未分类

2、搭建过程

2.1 准备宿主系统

准备一个 CentOS 7操作系统,具体要求如下:

  • 必须是 64 位操作系统

  • 建议内核在 3.8 以上

通过以下命令查看您的 CentOS 内核:

# uname -r

2.2 安装Docker

# yum install docker

可使用以下命令,查看 Docker 是否安装成功:

# docker version

若输出了 Docker 的版本号,则说明安装成功了,可通过以下命令启动 Docker 服务:

# systemctl start  docker.service

一旦 Docker 服务启动完毕,就可以开始使用 Docker 了。

2.3 下载镜像

以 CentOS 为例,下载一个 CentOS 的镜像:

# docker pull centos:7.2.1511

下载完成后,使用命令查看本地镜像列表:

# docker images
REPOSITORY        TAG        IMAGE ID      CREATED      VIRTUAL SIZE
docker.io/centos  7.2.1511   83ee614b834e  9 weeks ago  194.6 MB

2.4 启动容器

容器是在镜像的基础上来运行的,一旦容器启动了,我们就可以登录到容器中,安装自己所需的软件或应用程序。

使用以下命令即可启动容器:

# docker run -i -t -v /root/software/:/mnt/software/ 83ee /bin/bash

命令包含以下三个部分:

docker run <相关参数> <镜像 ID> <初始命令>

其中,相关参数包括:

  • -i:表示以“交互模式”运行容器

  • -t:表示容器启动后会进入其命令行

  • -v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>

本例中,所有安装程序都放在了宿主机的/root/software/目录下,现在需要将其挂载到容器的/mnt/software/目录下。

# pwd
/root/software

# ls
apache-tomcat-7.0.67.tar.gz  jdk1.7.0_79.tar.gz

初始命令表示一旦容器启动,需要运行的命令,此时使用“/bin/bash”,表示启动后直接进入bash shell。

2.5 安装软件

为了搭建 Java Web 运行环境,需要安装 JDK 与 Tomcat,下面的过程均在容器内部进行。本例中,选择/opt/目录作为安装目录,首先需要通过cd /opt/命令进入该目录。

2.5.1 安装JDK

首先,解压 JDK 程序包:

# tar -zxf /mnt/software/jdk1.7.0_79.tar.gz -C .

然后,移动 JDK 目录:

# mv jdk1.7.0_79/ /opt/jdk/

2.5.2 安装Tomcat

首先,解压Tomcat程序包:

# tar -zxf /mnt/software/apache-tomcat-7.0.67.tar.gz -C .

然后,移动Tomcat目录:

# mv apache-tomcat-7.0.67/ /opt/tomcat/

2.5.3 编写运行脚本

编写一个运行脚本,当启动容器时,运行该脚本,启动 Tomcat。

首先,创建运行脚本:

# touch /root/run.sh

# vi /root/run.sh

然后,编辑脚本内容如下:

#!/bin/bash

export JAVA_HOME=/opt/jdk/
export PATH=$JAVA_HOME/bin:$PATH

sh /opt/tomcat/bin/catalina.sh run

最后,为运行脚本添加执行权限:

# chmod u+x /root/run.sh

2.6 退出容器

当以上步骤全部完成后,可使用exit命令,退出容器。

随后,可使用如下命令查看正在运行的容器:

# docker ps

此时,应该看不到任何正在运行的程序,因为刚才已经使用exit命令退出的容器,此时容器处于停止状态,可使用如下命令查看所有容器:

# docker ps -a
CONTAINER ID  IMAGE  COMMAND     CREATED         STATUS                  
02bebc3f546a  83ee   "/bin/bash" 12 minutes ago  Exited (0) 7 seconds ago

记住以上CONTAINER ID(容器 ID),随后将通过该容器,创建一个可运行 Tomcat 镜像。

2.7 创建Tomcat镜像

使用以下命令,根据某个“容器 ID”来创建一个新的“镜像”:

# docker commit 02be mytomcat:1.0
65c88ec597e04812ec3b06b7749578bebcae3aa3d735b565ed25db6818d9d7f3

# docker images
REPOSITORY        TAG       IMAGE ID      CREATED             VIRTUAL SIZE
mytomcat          1.0       65c88ec597e0  About a minute ago  514.4 MB
docker.io/centos  7.2.1511  83ee614b834e  9 weeks ago         194.6 MB

该容器的ID是02be,所创建的镜像名是“mytomcat:1.0”,随后可使用镜像来启动Tomcat容器。

2.8 启动Tomcat容器

首先,新建/root/webapps/ROOT目录,并在该目录下创建一个index.html文件,文件内容如下:

<html>
<body>
<h2>Hello World!</h2>
</body>
</html>

正如上面所描述的那样,可以通过“镜像名”或“镜像 ID”来启动容器,与上次启动容器不同的是,现在不再进入容器的命令行,而是直接启动容器内部的 Tomcat 服务。此时,需要使用以下命令:

# docker run -d -p 58080:8080 -v /root/webapps/:/opt/tomcat/webapps/ --name mytomcat_1 mytomcat:1.0 /root/run.sh

其中,相关参数包括:

  • -d:表示以“守护模式”执行/root/run.sh脚本,此时 Tomcat 控制台不会出现在输出终端上。

  • -p:表示宿主机与容器的端口映射,此时将容器内部的 8080 端口映射为宿主机的 58080 端口,这样就向外界暴露了 58080 端口,可通过 Docker 网桥来访问容器内部的 8080 端口了。

  • -v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>

  • –name:表示容器名称,用一个有意义的名称命名即可。

在浏览器中,输入宿主IP和端口号,即可访问 Tomcat:

未分类

2.9 最终示意图:

未分类

2.10 停止Tomcat容器

# docker ps -a
CONTAINER ID  IMAGE         COMMAND         CREATED         STATUS        
f23598b6544d  mytomcat:1.0  "/root/run.sh"  6 minutes ago   Up 6 minutes  

# docker stop f235

2.11 移除容器

# docker ps -a
CONTAINER ID  IMAGE         COMMAND         CREATED        STATUS                         
f23598b6544d  mytomcat:1.0  "/root/run.sh"  8 minutes ago  Exited (137)

# docker rm f235
f235

# docker ps -a
CONTAINER ID  IMAGE         COMMAND         CREATED        STATUS

2.12 移除镜像

# docker images
REPOSITORY          TAG        IMAGE ID       CREATED         VIRTUAL SIZE
mytomcat            1.0        65c88ec597e0   31 minutes ago  514.4 MB
docker.io/centos    7.2.1511   83ee614b834e   9 weeks ago     194.6 MB

# docker rmi 65c8
Untagged: mytomcat:1.0
Deleted: 65c88ec597e04812ec3b06b7749578bebcae3aa3d735b565ed25db6818d9d7f3

# docker images
REPOSITORY          TAG        IMAGE ID       CREATED         VIRTUAL SIZE
docker.io/centos    7.2.1511   83ee614b834e   9 weeks ago     194.6 MB

PS:本文参考了大神博文:http://my.oschina.net/huangyong/blog/372491?fromerr=kHrZPM01,并在原文基础上,进行了部分添加修改。

简单几步搭建一个基于 Docker 的 Tomcat 运行环境!

前言

Docker 旨在提供一种应用程序的自动化部署解决方案,在 Linux 系统上迅速创建一个容器(轻量级虚拟机)并部署和运行应用程序,并通过配置文件可以轻松实现应用程序的自动化安装、部署和升级,非常方便。因为使用了容器,所以可以很方便的把生产环境和开发环境分开,互不影响,这是 docker 最普遍的一个玩法。更多的玩法还有大规模 web 应用、数据库部署、持续部署、集群、测试环境、面向服务的云计算、虚拟桌面 VDI 等等。

主观的印象:Docker 使用 Go 语言编写,用 cgroup 实现资源隔离,容器技术采用 LXC. 提供了能够独立运行 Unix 进程的轻量级虚拟化解决方案。它提供了一种在安全、可重复的环境中自动部署软件的方式。 LXC 命令有些复杂,若感兴趣,这里有一篇我以前写的基于 LXC ,(从无到有,搭建一个简单版的 JAVA PAAS 云平台),可以提前复习一下。

有关实现原理、相关理论、运用场景等,会在本系列后面书写,这里先来一个浅尝辄止,完全手动,基于 Docker 搭建一个 Tomcat 运行环境。先出来一个像模像样 Demo,可以见到效果,可能会让我们走的更远一些。

环境

本文所有环境,VMwareWorkStation 上运行 ubuntu-13.10-server-amd64, 注意是 64 位系统,理论上其它虚拟机也是完全可行的。

安装 Docker

Docker 0.7 版本需要 Linux 内核 3.8 支持,同时需要 AUFS 文件系统。

# 检查一下AUFS是否已安装sudo apt-get updatesudo apt-get install linux-image-extra-`uname -r`# 添加Docker repository keysudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"# 添加Docker repository,并安装Dockersudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"sudo apt-get updatesudo apt-get install lxc-docker# 检查Docker是否已安装成功sudo docker version# 终端输出 Client version: 0.7.1Go version (client): go1.2Git commit (client): 88df052Server version: 0.7.1Git commit (server): 88df052Go version (server): go1.2Last stable version: 0.7.1

去除掉 sudo

在 Ubuntu 下,在执行 Docker 时,每次都要输入 sudo,同时输入密码,很累人的,这里微调一下,把当前用户执行权限添加到相应的 docker 用户组里面。

# 添加一个新的docker用户组sudo groupadd docker# 添加当前用户到docker用户组里,注意这里的yongboy为ubuntu server登录用户名sudo gpasswd -a yongboy docker# 重启Docker后台监护进程sudo service docker restart# 重启之后,尝试一下,是否生效docker version#若还未生效,则系统重启,则生效sudo reboot

安装一个 Docker 运行实例 -ubuntu 虚拟机

Docker 安装完毕,后台进程也自动启动了,可以安装虚拟机实例(这里直接拿官方演示使用的 learn/tutorial 镜像为例):

docker pull learn/tutorial

安装完成之后,看看效果

docker run learn/tutorial /bin/echo hello world

交互式进入新安装的虚拟机中

docker run -i -t learn/tutorial /bin/bash

会看到:

root@51774a81beb3:/#

说明已经进入交互式环境。

安装 SSH 终端服务器,便于我们外部使用 SSH 客户端登陆访问

apt-get updateapt-get install openssh-serverwhich sshd/usr/sbin/sshdmkdir /var/run/sshdpasswd #输入用户密码,我这里设置为123456,便于SSH客户端登陆使用exit #退出

获取到刚才操作的实例容器 ID

#docker ps -lCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES51774a81beb3 learn/tutorial:latest /bin/bash 3 minutes ago Exit 0 thirsty_pasteur

可以看到当前操作的容器 ID 为 51774a81beb3 。注意了,一旦进行所有操作,都需要提交保存,便于 SSH 登陆使用:

docker commit 51774a81beb3 learn/tutorial

以后台进程方式长期运行此镜像实例:

docker run -d -p 22 -p 80:8080 learn/tutorial /usr/sbin/sshd -D

ubuntu 容器内运行着的 SSH Server 占用 22 端口,-p 22 进行指定。-p 80:8080 指的是,我们 ubuntu 将会以 8080 端口运行 tomcat ,但对外(容器外)映射的端口为 80 。

这时,查看一下,是否成功运行。

#docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES871769a4f5ea learn/tutorial:latest /usr/sbin/sshd -D About a minute ago Up About a minute 0.0.0.0:49154->22/tcp, 0.0.0.0:80->8080/tcp focused_poincare

注意这里的分配随机的 SSH 连接端口号为 49154:

ssh [email protected] -p 49154

输入可以口令,是不是可以进入了?你一旦控制了 SSH ,剩下的事情就很简单了,安装 JDK ,安装 tomcat 等,随你所愿了。以下为安装脚本:

# 在ubuntu 12.04上安装oracle jdk 7apt-get install python-software-propertiesadd-apt-repository ppa:webupd8team/javaapt-get updateapt-get install -y wgetapt-get install oracle-java7-installerjava -version# 下载tomcat 7.0.47wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.47/bin/apache-tomcat-7.0.47.tar.gz# 解压,运行tar xvf apache-tomcat-7.0.47.tar.gzcd apache-tomcat-7.0.47bin/startup.sh

默认情况下,tomcat 会占用 8080 端口,刚才在启动镜像实例的时候,指定了 -p 80:8080 ,ubuntu 镜像实例/容器,开放 8080 端口,映射到宿主机端口就是 80 。知道宿主机 IP 地址,那就可以自由访问了。在宿主机上,通过 cur l测试一下即可:

curl http://192.168.190.131

当然,你也可以使用浏览器访问啦。

真实情况,可能不会让 tomcat 直接对外开放 80 端口,一般都会位于 nginx/apache 或者防火墙的后面,上面仅为演示。

小结

在 Docker 帮助下搭建一个 Tomcat 运行时环境,总体很简单,让我们看到了 PAAS 的身影。不错,使用 Docker 作为 PAAS 底层服务,本身就不复杂。以后有时间,会谈一谈如何使用脚本文件构建一个镜像实例,同时会谈一谈 Docker 的实现原理和机制等。

docker构建 mongodb 集群服务

安装

docker run -p 27018:27017 -v /root/docker/mongo/data:/data/db  -d --name=mongo361 mongo --bind_ip_all --auth

进入容器

docker exec -it mongo361 mongo admin

创建 所有数据库角色

db.createUser({ user: 'zan', pwd: 'zan', roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] });

更多角色说明: https://docs.mongodb.com/manual/reference/built-in-roles/#built-in-roles

认证进入 操作状态

db.auth("zan","zan")
use test

test 只读账号

db.createUser({user:"test",pwd:"test",roles:[{role: "read", db: "test"}]})

test1 读写账号

db.createUser({user:"test1",pwd:"test",roles:[{role: "readWrite", db: "test"}]})

使用docker直接运行mongodb,解决Kitematic崩溃问题

在新大学习webapp 使用express mongodb数据库,并且mongodb是在docker容器下的,docker自带的用户界面UI Kitematic经常崩溃,
但是docker却没有问题,我就想能不能在 terminal 使用mongodb ,下面我就简单说下怎么使用docker的

未分类

先看看后面会使用到的几个命令

docker ps
docker images
docker start
docker stop
docker pull
docker run
docker exec
docker   COMMAND --help 最重要的一个

1. 使用terminal

未分类

Windows自带的powershell
打开powershell terminal 使用 docker ps 看下docker容器中都启动了那些服务.

未分类

如果已经运行了 mongodb 可以使用 docker stop SERVER-NAME SERVER-NAME 是使用 docker ps 中查看到的;

2. 下载镜像文件

使用 docker images 查看是否有可用的镜像文件

如果没有可以使用 docker pull mongodb 命令从官网上下载 https://store.docker.com/ 或者直接使用
https://store.docker.com/images/mongo 下载

未分类

然后根据自己现在运行的docker容器类型选择,默认是linux容器,下图是查看方式.点一下就会切换到windows containers.

未分类

3. 在docker容器中安装mongodb

docker run -d --name mongo-test -p 27017:27017 mongo

-d Run container in background and print container ID 老实说我也不太懂
– name 是指给你的mongodb起个名字
-p 这个参数一定要有,不然你本地的webapp连接不到数据库,
它的意思是将虚拟机中的mongodb的端口号(mongodb端口号使用docker ps 查看)映射到你的电脑localhost:27017上面 ,当然你的映射端 口号根据自己需要可以自定义.

4. 进入到 mongdb 创建数据库

使用如下命令

docker exec -it mongo-test mongo 

看下数据库 show dbs;

创建数据库 use myapp;

好了现在可以试试你的webapp是不是能连接上了. localhost:27017