Skip to content

Commit 3d8229a

Browse files
committed
initial
1 parent 1a5b0d1 commit 3d8229a

File tree

8 files changed

+274
-3
lines changed

8 files changed

+274
-3
lines changed

Dockerfile

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,24 @@ COPY ./docker-entrypoint.sh /
4747
RUN mkdir /home/couchdb/couchdb/data /home/couchdb/couchdb/etc/default.d \
4848
&& chown -R couchdb:couchdb /home/couchdb/couchdb/
4949

50+
# Install nodejs
51+
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - \
52+
&& apt-get install -y nodejs \
53+
&& npm install npm -g
54+
55+
# docker-discover-tasks helps the nodes discover each other
56+
RUN npm install -g docker-discover-tasks
57+
5058
WORKDIR /home/couchdb/couchdb
5159

5260
EXPOSE 5984 4369 9100-9200
5361

5462
VOLUME ["/home/couchdb/couchdb/data"]
5563

56-
ENTRYPOINT ["tini", "--", "/docker-entrypoint.sh"]
57-
CMD ["/home/couchdb/couchdb/bin/couchdb"]
64+
COPY couchdb-process.sh /couchdb-process.sh
65+
COPY discover-process.sh /discover-process.sh
66+
COPY set-up-process.sh /set-up-process.sh
67+
COPY wait-for-it.sh /wait-for-it.sh
68+
COPY wrapper.sh /wrapper.sh
69+
70+
CMD ["/wrapper.sh"]

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,26 @@
11
# couchdb-docker-service
22
CouchDB as a docker swarm service
3+
4+
TODO
5+
---
6+
7+
docker swarm init --advertise-addr
8+
9+
docker network create \
10+
--driver overlay \
11+
--subnet 10.0.9.0/24 \
12+
--opt encrypted \
13+
couchdb-network
14+
15+
docker service create --replicas 2 --name couchdb --network couchdb-network \
16+
-p 5984:5984 \
17+
-e COUCHDB_COOKIE="mycookie" \
18+
-e COUCHDB_USER="admin" \
19+
-e COUCHDB_PASSWORD="admin" \
20+
-e COUCHDB_HASHED_PASSWORD="-pbkdf2-b1eb7a68b0778a529c68d30749954e9e430417fb,4da0f8f1d98ce649a9c5a3845241ae24,10" \
21+
-e COUCHDB_SECRET="mysecret" \
22+
-e NODENAME="{{.Service.Name}}{{.Task.Slot}}" \
23+
-e SERVICE_NAME="{{.Service.Name}}" \
24+
-e TASK_SLOT="{{.Task.Slot}}" \
25+
--hostname="couchdb{{.Task.Slot}}" \
26+
redgeoff/couchdb

couchdb-process.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
/docker-entrypoint.sh /home/couchdb/couchdb/bin/couchdb

discover-process.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
docker-discover-tasks -s $SERVICE_NAME -p 3000 > /var/log/docker-discover-tasks.log

docker-entrypoint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ if [ "$1" = '/home/couchdb/couchdb/bin/couchdb' ]; then
1414
fi
1515
fi
1616

17-
if [ "$COUCHDB_USER" ] && [ "$COUCHDB_PASSWORD" ] && [ -z "$COUCHDB_SYNC_ADMINS_NODE" ]; then
17+
if [ "$COUCHDB_USER" ] && [ "$COUCHDB_PASSWORD" ] && [ -z "$COUCHDB_HASHED_PASSWORD" ]; then
1818
# Create admin
1919
printf "[admins]\n%s = %s\n" "$COUCHDB_USER" "$COUCHDB_PASSWORD" > /home/couchdb/couchdb/etc/local.d/docker.ini
2020
chown couchdb:couchdb /home/couchdb/couchdb/etc/local.d/docker.ini

set-up-process.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
# The primary node is couchdb1 and is the single node with which all secondary nodes register their
4+
# membership. The primary node and secondary node designation only really matters during the setup
5+
# process and is only used to implement a scalable service architecture.
6+
7+
if [ $TASK_SLOT -eq 1 ]; then
8+
echo "Setting up primary node..."
9+
# TODO: check couchdb1:5984/_users to make sure DB doesn't already exist before executing the
10+
# following
11+
12+
# Create system databases
13+
curl -X PUT http://$COUCHDB_USER:$COUCHDB_PASSWORD@couchdb1:5984/_users
14+
curl -X PUT http://$COUCHDB_USER:$COUCHDB_PASSWORD@couchdb1:5984/_replicator
15+
curl -X PUT http://$COUCHDB_USER:$COUCHDB_PASSWORD@couchdb1:5984/_global_changes
16+
else
17+
echo "Setting up secondary node..."
18+
19+
# Register membership
20+
curl -X PUT http://$COUCHDB_USER:$COUCHDB_PASSWORD@couchdb1:5986/_nodes/couchdb@couchdb$TASK_SLOT -d {}
21+
fi

wait-for-it.sh

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env bash
2+
# Use this script to test if a given TCP host/port are available
3+
4+
cmdname=$(basename $0)
5+
6+
echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
7+
8+
usage()
9+
{
10+
cat << USAGE >&2
11+
Usage:
12+
$cmdname host:port [-s] [-t timeout] [-- command args]
13+
-h HOST | --host=HOST Host or IP under test
14+
-p PORT | --port=PORT TCP port under test
15+
Alternatively, you specify the host and port as host:port
16+
-s | --strict Only execute subcommand if the test succeeds
17+
-q | --quiet Don't output any status messages
18+
-t TIMEOUT | --timeout=TIMEOUT
19+
Timeout in seconds, zero for no timeout
20+
-- COMMAND ARGS Execute command with args after the test finishes
21+
USAGE
22+
exit 1
23+
}
24+
25+
wait_for()
26+
{
27+
if [[ $TIMEOUT -gt 0 ]]; then
28+
echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"
29+
else
30+
echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"
31+
fi
32+
start_ts=$(date +%s)
33+
while :
34+
do
35+
(echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1
36+
result=$?
37+
if [[ $result -eq 0 ]]; then
38+
end_ts=$(date +%s)
39+
echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"
40+
break
41+
fi
42+
sleep 1
43+
done
44+
return $result
45+
}
46+
47+
wait_for_wrapper()
48+
{
49+
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
50+
if [[ $QUIET -eq 1 ]]; then
51+
timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
52+
else
53+
timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
54+
fi
55+
PID=$!
56+
trap "kill -INT -$PID" INT
57+
wait $PID
58+
RESULT=$?
59+
if [[ $RESULT -ne 0 ]]; then
60+
echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
61+
fi
62+
return $RESULT
63+
}
64+
65+
# process arguments
66+
while [[ $# -gt 0 ]]
67+
do
68+
case "$1" in
69+
*:* )
70+
hostport=(${1//:/ })
71+
HOST=${hostport[0]}
72+
PORT=${hostport[1]}
73+
shift 1
74+
;;
75+
--child)
76+
CHILD=1
77+
shift 1
78+
;;
79+
-q | --quiet)
80+
QUIET=1
81+
shift 1
82+
;;
83+
-s | --strict)
84+
STRICT=1
85+
shift 1
86+
;;
87+
-h)
88+
HOST="$2"
89+
if [[ $HOST == "" ]]; then break; fi
90+
shift 2
91+
;;
92+
--host=*)
93+
HOST="${1#*=}"
94+
shift 1
95+
;;
96+
-p)
97+
PORT="$2"
98+
if [[ $PORT == "" ]]; then break; fi
99+
shift 2
100+
;;
101+
--port=*)
102+
PORT="${1#*=}"
103+
shift 1
104+
;;
105+
-t)
106+
TIMEOUT="$2"
107+
if [[ $TIMEOUT == "" ]]; then break; fi
108+
shift 2
109+
;;
110+
--timeout=*)
111+
TIMEOUT="${1#*=}"
112+
shift 1
113+
;;
114+
--)
115+
shift
116+
CLI="$@"
117+
break
118+
;;
119+
--help)
120+
usage
121+
;;
122+
*)
123+
echoerr "Unknown argument: $1"
124+
usage
125+
;;
126+
esac
127+
done
128+
129+
if [[ "$HOST" == "" || "$PORT" == "" ]]; then
130+
echoerr "Error: you need to provide a host and port to test."
131+
usage
132+
fi
133+
134+
TIMEOUT=${TIMEOUT:-15}
135+
STRICT=${STRICT:-0}
136+
CHILD=${CHILD:-0}
137+
QUIET=${QUIET:-0}
138+
139+
if [[ $CHILD -gt 0 ]]; then
140+
wait_for
141+
RESULT=$?
142+
exit $RESULT
143+
else
144+
if [[ $TIMEOUT -gt 0 ]]; then
145+
wait_for_wrapper
146+
RESULT=$?
147+
else
148+
wait_for
149+
RESULT=$?
150+
fi
151+
fi
152+
153+
if [[ $CLI != "" ]]; then
154+
if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then
155+
echoerr "$cmdname: strict mode, refusing to execute subprocess"
156+
exit $RESULT
157+
fi
158+
exec $CLI
159+
else
160+
exit $RESULT
161+
fi

wrapper.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
# Adaptation of https://docs.docker.com/engine/admin/multi-service_container/
4+
5+
# Start the discover process
6+
/discover-process.sh &
7+
status=$?
8+
if [ $status -ne 0 ]; then
9+
echo "Failed to start discover-process: $status"
10+
exit $status
11+
fi
12+
13+
# Start the couchdb process
14+
/couchdb-process.sh &
15+
status=$?
16+
if [ $status -ne 0 ]; then
17+
echo "Failed to start couchdb-process: $status"
18+
exit $status
19+
fi
20+
21+
# Start the set-up process in the foreground after the couchdb1 is ready. We expect this process to
22+
# complete and then the script will continue on and monitor the other 2 processes.
23+
/wait-for-it.sh couchdb1:5984 -t 300 -- /set-up-process.sh
24+
25+
# Naive check runs checks once a minute to see if either of the processes exited. The container will
26+
# exit with an error
27+
28+
while /bin/true; do
29+
DISCOVER_STATUS=$(ps aux | grep discover-process | grep -v grep | wc -l)
30+
COUCHDB_STATUS=$(ps aux | grep couchdb-process | grep -v grep | wc -l)
31+
32+
# If the greps above find anything, they will exit with 0 status
33+
# If they are not both 0, then something is wrong
34+
35+
if [ $DISCOVER_STATUS -ne 1 ]; then
36+
echo "discover-process has exited."
37+
exit -1
38+
fi
39+
40+
if [ $COUCHDB_STATUS -ne 1 ]; then
41+
echo "couchdb-processes has exited."
42+
exit -1
43+
fi
44+
45+
sleep 30
46+
done

0 commit comments

Comments
 (0)