文章永久连接:https://tech.souyunku.com/5103
MongoDB 是当下最流行的 NoSQL 数据库之一,Docker 安装 apache 的方式有两种
如果你是 Docker 初学者,如果你以后长期使用 mongodb ,我们建议你两种方法都试一试,为什么呢?
原因很简单,第一种方法,简单快捷,第二种方法,就是尝试自己编译安装
1. docker pull mongodb
如果想以最简单的方式安装 MongoDB, 可以直接使用 docker pull mongo 命令
流程如下
1、 查找 Docker Hub 上的 mongodb 镜像
[root@localhost ~]# docker search mongodb
NAME ... OFFICIAL ...
mongo ... [OK] ...
mongo-express [OK] ...
列表很多,我们推荐你使用 `OFFICIAL = OK` 的那两条
1. `mongo` 是官方数据库
2. `mongo-express` 是官方使用 `Node.js` 开发的 `MongoDB` 管理后台
2、 拉取官方最新的 MongoDB 镜像
[root@localhost ~]# docker pull mongo
Using default tag: latest
...
3、 稍等片刻,下载完成后就可以在本地镜像列表里看到 mongo 的镜像了
[root@localhost apache]# docker images mongodb
REPOSITORY TAG IMAGE ID CREATED SIZE
mongo latest f93ff881751f 5 days ago 367.6 MB
2. 通过 Dockerfile 文件构建
如果你是运维工程师,我们推荐你使用 Dockerfile 文件构建 mongodb 镜像
因为可以加深对安装 mongodb 的理解
现在,我们一步一步使用 Dockerfile 文件构建 mongodb 镜像吧
1、 创建目录 mongo 用于存放后面的相关东西
[root@localhost ~]# mkdir -p ~/mongo/db
<table>
<thead>
<tr>
<th align="left">目录</th>
<th align="left">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">mongo</td>
<td align="left">该目录存放 <code>Dockerfile</code> 文件和 <code>db</code> 数据库目录</td>
</tr>
<tr>
<td align="left">mongo/db</td>
<td align="left">该目录将映射为 mongodb 容器的数据库目录</td>
</tr>
</tbody>
</table>
2、 进入创建的 mongo 目录,创建 docker-entrypoint.sh 脚本用于管理 MongoDB 数据库
[root@localhost ~]# cd mongo
[root@localhost mongo] touch docker-entrypoint.sh
[root@localhost mongo] chmod +x docker-entrypoint.sh
[root@localhost mongo] vi docker-entrypoint.sh
然后输入以下内容
# !/bin/bash
# 注意去掉上一行 # ! 之间的空格
set -Eeuo pipefail
if [ "${1:0:1}" = '-' ]; then
set -- mongod "$@"
fi
originalArgOne="$1"
# allow the container to be started with `--user`
# all mongo* commands should be dropped to the correct user
if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then
if [ "$originalArgOne" = 'mongod' ]; then
chown -R mongodb /data/configdb /data/db
fi
# make sure we can write to stdout and stderr as "mongodb"
# (for our "initdb" code later; see "--logpath" below)
chown --dereference mongodb "/proc/$$/fd/1" "/proc/$$/fd/2" || :
# ignore errors thanks to https://github.com/docker-library/mongo/issues/149
exec gosu mongodb "$BASH_SOURCE" "$@"
fi
# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients.
# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux
if [[ "$originalArgOne" == mongo* ]]; then
numa='numactl --interleave=all'
if $numa true &> /dev/null; then
set -- $numa "$@"
fi
fi
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments)
_mongod_hack_have_arg() {
local checkArg="$1"; shift
local arg
for arg; do
case "$arg" in
"$checkArg"|"$checkArg"=*)
return 0
;;
esac
done
return 1
}
# _mongod_hack_get_arg_val '--some-arg' "$@"
_mongod_hack_get_arg_val() {
local checkArg="$1"; shift
while [ "$#" -gt 0 ]; do
local arg="$1"; shift
case "$arg" in
"$checkArg")
echo "$1"
return 0
;;
"$checkArg"=*)
echo "${arg#$checkArg=}"
return 0
;;
esac
done
return 1
}
declare -a mongodHackedArgs
# _mongod_hack_ensure_arg '--some-arg' "$@"
# set -- "${mongodHackedArgs[@]}"
_mongod_hack_ensure_arg() {
local ensureArg="$1"; shift
mongodHackedArgs=( "$@" )
if ! _mongod_hack_have_arg "$ensureArg" "$@"; then
mongodHackedArgs+=( "$ensureArg" )
fi
}
# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@"
# set -- "${mongodHackedArgs[@]}"
_mongod_hack_ensure_no_arg() {
local ensureNoArg="$1"; shift
mongodHackedArgs=()
while [ "$#" -gt 0 ]; do
local arg="$1"; shift
if [ "$arg" = "$ensureNoArg" ]; then
continue
fi
mongodHackedArgs+=( "$arg" )
done
}
# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@"
# set -- "${mongodHackedArgs[@]}"
_mongod_hack_ensure_no_arg_val() {
local ensureNoArg="$1"; shift
mongodHackedArgs=()
while [ "$#" -gt 0 ]; do
local arg="$1"; shift
case "$arg" in
"$ensureNoArg")
shift # also skip the value
continue
;;
"$ensureNoArg"=*)
# value is already included
continue
;;
esac
mongodHackedArgs+=( "$arg" )
done
}
# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@"
# set -- "${mongodHackedArgs[@]}"
_mongod_hack_ensure_arg_val() {
local ensureArg="$1"; shift
local ensureVal="$1"; shift
_mongod_hack_ensure_no_arg_val "$ensureArg" "$@"
mongodHackedArgs+=( "$ensureArg" "$ensureVal" )
}
# _js_escape 'some "string" value'
_js_escape() {
jq --null-input --arg 'str' "$1" '$str'
}
jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json"
tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json"
_parse_config() {
if [ -s "$tempConfigFile" ]; then
return 0
fi
local configPath
if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then
# if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys)
# see https://docs.mongodb.com/manual/reference/configuration-options/
mongo --norc --nodb --quiet --eval "load('/js-yaml.js'); printjson(jsyaml.load(cat($(_js_escape "$configPath"))))" > "$jsonConfigFile"
jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile"
return 0
fi
return 1
}
dbPath=
_dbPath() {
if [ -n "$dbPath" ]; then
echo "$dbPath"
return
fi
if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then
if _parse_config "$@"; then
dbPath="$(jq '.storage.dbPath' "$jsonConfigFile")"
fi
fi
: "${dbPath:=/data/db}"
echo "$dbPath"
}
if [ "$originalArgOne" = 'mongod' ]; then
file_env 'MONGO_INITDB_ROOT_USERNAME'
file_env 'MONGO_INITDB_ROOT_PASSWORD'
# pre-check a few factors to see if it's even worth bothering with initdb
shouldPerformInitdb=
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
# if we have a username/password, let's set "--auth"
_mongod_hack_ensure_arg '--auth' "$@"
set -- "${mongodHackedArgs[@]}"
shouldPerformInitdb='true'
elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
cat >&2 <<-'EOF'
error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD'
both must be specified for a user to be created
EOF
exit 1
fi
if [ -z "$shouldPerformInitdb" ]; then
# if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh|*.js) # this should match the set of files we check for below
shouldPerformInitdb="$f"
break
;;
esac
done
fi
# check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts)
if [ -n "$shouldPerformInitdb" ]; then
dbPath="$(_dbPath "$@")"
for path in \
"$dbPath/WiredTiger" \
"$dbPath/journal" \
"$dbPath/local.0" \
"$dbPath/storage.bson" \
; do
if [ -e "$path" ]; then
shouldPerformInitdb=
break
fi
done
fi
if [ -n "$shouldPerformInitdb" ]; then
mongodHackedArgs=( "$@" )
if _parse_config "$@"; then
_mongod_hack_ensure_arg_val --config "$tempConfigFile" "${mongodHackedArgs[@]}"
fi
_mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}"
_mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}"
_mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}"
# remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control)
# https://github.com/docker-library/mongo/issues/211
_mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}"
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
_mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}"
fi
sslMode="$(_mongod_hack_have_arg '--sslPEMKeyFile' "$@" && echo 'allowSSL' || echo 'disabled')" # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters"
_mongod_hack_ensure_arg_val --sslMode "$sslMode" "${mongodHackedArgs[@]}"
if stat "/proc/$$/fd/1" > /dev/null && [ -w "/proc/$$/fd/1" ]; then
# https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251
# https://github.com/docker-library/mongo/issues/164#issuecomment-293965668
_mongod_hack_ensure_arg_val --logpath "/proc/$$/fd/1" "${mongodHackedArgs[@]}"
else
initdbLogPath="$(_dbPath "$@")/docker-initdb.log"
echo >&2 "warning: initdb logs cannot write to '/proc/$$/fd/1', so they are in '$initdbLogPath' instead"
_mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}"
fi
_mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}"
pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid"
rm -f "$pidfile"
_mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}"
"${mongodHackedArgs[@]}" --fork
mongo=( mongo --host 127.0.0.1 --port 27017 --quiet )
# check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc)
# https://jira.mongodb.org/browse/SERVER-16292
tries=30
while true; do
if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then
# bail ASAP if "mongod" isn't even running
echo >&2
echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?"
echo >&2
exit 1
fi
if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
# success!
break
fi
(( tries-- ))
if [ "$tries" -le 0 ]; then
echo >&2
echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?"
echo >&2
exit 1
fi
sleep 1
done
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
rootAuthDatabase='admin'
"${mongo[@]}" "$rootAuthDatabase" <<-EOJS
db.createUser({
user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"),
pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"),
roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ]
})
EOJS
fi
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
echo
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done
"$@" --pidfilepath="$pidfile" --shutdown
rm -f "$pidfile"
echo
echo 'MongoDB init process complete; ready for start up.'
echo
fi
# MongoDB 3.6+ defaults to localhost-only binding
haveBindIp=
if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then
haveBindIp=1
elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then
haveBindIp=1
fi
if [ -z "$haveBindIp" ]; then
# so if no "--bind_ip" is specified, let's add "--bind_ip_all"
set -- "$@" --bind_ip_all
fi
unset "${!MONGO_INITDB_@}"
fi
rm -f "$jsonConfigFile" "$tempConfigFile"
exec "$@"
3、 在 mongo 目录下创建 Dockerfile
[root@localhost mongo]# vi Dockerfile
然后输入以下内容
FROM debian:jessie-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
jq \
numactl \
&& rm -rf /var/lib/apt/lists/*
# grab gosu for easy step-down from root (https://github.com/tianon/gosu/releases)
ENV GOSU_VERSION 1.10
# grab "js-yaml" for parsing mongod's YAML config files (https://github.com/nodeca/js-yaml/releases)
ENV JSYAML_VERSION 3.10.0
RUN set -ex; \
\
apt-get update; \
apt-get install -y --no-install-recommends \
wget \
; \
rm -rf /var/lib/apt/lists/*; \
\
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc; \
chmod +x /usr/local/bin/gosu; \
gosu nobody true; \
\
wget -O /js-yaml.js "https://github.com/nodeca/js-yaml/raw/${JSYAML_VERSION}/dist/js-yaml.js"; \
# TODO some sort of download verification here
\
apt-get purge -y --auto-remove wget
RUN mkdir /docker-entrypoint-initdb.d
ENV GPG_KEYS \
# pub rsa4096 2017-11-15 [SC] [expires: 2019-11-15]
# BD8C 80D9 C729 D005 24E0 68E0 3DAB 7171 3396 F72B
# uid [ unknown] MongoDB 3.8 Release Signing Key <packaging@mongodb.com>
BD8C80D9C729D00524E068E03DAB71713396F72B
# https://docs.mongodb.com/manual/tutorial/verify-mongodb-packages/#download-then-import-the-key-file
RUN set -ex; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done; \
gpg --export $GPG_KEYS > /etc/apt/trusted.gpg.d/mongodb.gpg; \
rm -r "$GNUPGHOME"; \
apt-key list
# Allow build-time overrides (eg. to build image with MongoDB Enterprise version)
# Options for MONGO_PACKAGE: mongodb-org OR mongodb-enterprise
# Options for MONGO_REPO: repo.mongodb.org OR repo.mongodb.com
# Example: docker build --build-arg MONGO_PACKAGE=mongodb-enterprise --build-arg MONGO_REPO=repo.mongodb.com .
ARG MONGO_PACKAGE=mongodb-org-unstable
ARG MONGO_REPO=repo.mongodb.org
ENV MONGO_PACKAGE=${MONGO_PACKAGE} MONGO_REPO=${MONGO_REPO}
ENV MONGO_MAJOR 3.7
ENV MONGO_VERSION 3.7.9
RUN echo "deb http://$MONGO_REPO/apt/debian jessie/${MONGO_PACKAGE%-unstable}/$MONGO_MAJOR main" | tee "/etc/apt/sources.list.d/${MONGO_PACKAGE%-unstable}.list"
RUN set -x \
&& apt-get update \
&& apt-get install -y \
${MONGO_PACKAGE}=$MONGO_VERSION \
${MONGO_PACKAGE}-server=$MONGO_VERSION \
${MONGO_PACKAGE}-shell=$MONGO_VERSION \
${MONGO_PACKAGE}-mongos=$MONGO_VERSION \
${MONGO_PACKAGE}-tools=$MONGO_VERSION \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /var/lib/mongodb \
&& mv /etc/mongod.conf /etc/mongod.conf.orig
RUN mkdir -p /data/db /data/configdb \
&& chown -R mongodb:mongodb /data/db /data/configdb
VOLUME /data/db /data/configdb
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 27017
CMD ["mongod"]
这些内容,基本都是官方给的 [Dockerfile][]
4、 通过 Dockerfile 创建一个镜像 ms-mongodb,你可以替换成你自己的名字
[root@localhost mongo]# docker build -t ms-mongo:3.7 .
5、 稍等片刻,创建完成后,可以在本地的镜像列表里查找到刚刚创建的镜像
[root@localhost mongo]# docker images mongo:3.7
REPOSITORY TAG IMAGE ID CREATED SIZE
ms-mongo 3.7 f0f3e4beccef 11 days ago 323 MB
> 这次自己编译的竟然比官方镜像小....
GitHub 下载加速
从 GitHub 下载文件非常慢,因为下载链接指向了 Amazon 的服务器
下载地址是 http://github-cloud.s3.amazonaws.com/,从国内访问 Amazon 非常慢,所以总是下载失败,解决方法时更改 hosts 文件,使该域名指向香港的服务器219.76.4.4 github-cloud.s3.amazonaws.com
运行 ms-mongo:3.7 容器
可以使用下面的命令运行我们刚刚创建的 ms-mongo:3.7 镜像
[root@localhost mongo]# docker run -d -p 27017:27017 -v $PWD/db:/data/db ms-mongo:3.7
dbe5d334e0063332633fe78fcc031c26851cbb1c5d589d50414e7bd37471671d
参数说明:
1、 -p 27017:27017
将容器的 `27017` 端口映射到主机的 `27017` 端口
2、 -v $PWD/db:/data/db
将主机中当前目录下的 `db` 挂载到容器的 `/data/db`,作为 mongo 数据存储目录
查看容器启动情况
[root@localhost mongo]# docker ps -a
CONTAINER ID IMAGE COMMAND ...
dbe5d334e006 ms-mongo:3.7 "docker-entrypoint.sh" ...
查看容器的 IP
可以使用命令 docker inspect 查看容器的 IP
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container_id>
例如可以使用下面的命令查看刚刚创建的容器的 IP
[root@localhost mongo] docker inspect --format '{{ .NetworkSettings.IPAddress }}' dbe5d334e006
172、17.0.2
连接到 mongo 镜像
可以使用 mongo 镜像执行 mongo 命令连接到刚启动的容器, 主机 IP 为 172.17.0.2
[root@localhost mongo]# docker run -it ms-mongo:3.7 mongo --host 172.17.0.2
MongoDB shell version v3.6.5
connecting to: mongodb://172.17.0.2:27017/
MongoDB server version: 3.6.5
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
2018-05-18T14:01:20.078+0000 I STORAGE [main] In File::open(), ::open for '/home/mongodb/.mongorc.js' failed with No such file or directory
Server has startup warnings:
2018-05-18T13:59:12.821+0000 I CONTROL [initandlisten]
2018-05-18T13:59:12.821+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-05-18T13:59:12.821+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2018-05-18T13:59:12.821+0000 I CONTROL [initandlisten]
干货推荐
附录:Docker 教程:系列文章
- 一、Docker 基础教程
- 二、Docker 架构
- 三、Ubuntu 安装 Docker
- 四、CentOS Docker 安装
- 五、Windows 安装 Docker
- 六、Docker run 运行镜像
- 七、Docker 容器
- 八、Docker top 查看容器进程
- 九、Docker inspect 容器元数据
- 十、Docker start 启动容器
- 十一、Docker restart 重启容器
- 十二、Docker rm 删除已停止的容器
- 十三、Docker 命名容器
- 十四、Docker 容器运行 Web 应用
- 十五、Docker 端口映射
- 十六、Docker images 本地镜像列表
- 十七、Docker 查找镜像
- 十八、Docker commit 更新镜像
- 十九、Docker Dockerfile 创建镜像
- 二十、Docker build 构建镜像
- 二十一、Docker 镜像打标签
- 二十二、Docker 部署 Nginx 环境
- 二十三、Docker 部署 PHP 环境
- 二十四、Docker 安装 MySQL
- 二十五、Docker 安装 Tomcat
- 二十六、Docker 安装 Python
- 二十七、Docker 安装 Redis
- 【当前读到】二十八、Docker 安装 MongoDB
- 二十九、Docker 安装 Apache
- 三十、Docker 命令大全