diff --git a/baseimage/initializeBaseUbuntuImage.sh b/baseimage/initializeBaseUbuntuImage.sh index 7e8dbe9e8..576e4c741 100644 --- a/baseimage/initializeBaseUbuntuImage.sh +++ b/baseimage/initializeBaseUbuntuImage.sh @@ -68,7 +68,7 @@ fi iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT iptables -A INPUT -p udp --sport 53 -j ACCEPT -iptables -A INPUT -s 172.17.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: +iptables -A INPUT -s 172.18.0.0/16 -j ACCEPT # required to accept any connections from apps to our IP: # loopback iptables -A INPUT -i lo -j ACCEPT diff --git a/src/addons.js b/src/addons.js index 6ca20f23b..688437ff4 100644 --- a/src/addons.js +++ b/src/addons.js @@ -7,7 +7,6 @@ exports = module.exports = { restoreAddons: restoreAddons, getEnvironment: getEnvironment, - getLinksSync: getLinksSync, getBindsSync: getBindsSync, getContainerNamesSync: getContainerNamesSync, @@ -209,34 +208,6 @@ function getEnvironment(app, callback) { appdb.getAddonConfigByAppId(app.id, callback); } -function getLinksSync(app, addons) { - assert.strictEqual(typeof app, 'object'); - assert(!addons || typeof addons === 'object'); - - var links = [ ]; - - if (!addons) return links; - - var addMail = false; - - for (var addon in addons) { - switch (addon) { - case 'mysql': links.push('mysql:mysql'); break; - case 'postgresql': links.push('postgresql:postgresql'); break; - case 'sendmail': addMail = true; break; - case 'recvmail': addMail = true; break; - case 'email': addMail = true; break; - case 'redis': links.push('redis-' + app.id + ':redis-' + app.id); break; - case 'mongodb': links.push('mongodb:mongodb'); break; - default: break; - } - } - - if (addMail) links.push('mail:mail'); - - return links; -} - function getBindsSync(app, addons) { assert.strictEqual(typeof app, 'object'); assert(!addons || typeof addons === 'object'); @@ -334,10 +305,10 @@ function setupSimpleAuth(app, options, callback) { if (error) return callback(error); var env = [ - 'SIMPLE_AUTH_SERVER=172.17.0.1', + 'SIMPLE_AUTH_SERVER=172.18.0.1', 'SIMPLE_AUTH_PORT=' + config.get('simpleAuthPort'), - 'SIMPLE_AUTH_URL=http://172.17.0.1:' + config.get('simpleAuthPort'), // obsolete, remove - 'SIMPLE_AUTH_ORIGIN=http://172.17.0.1:' + config.get('simpleAuthPort'), + 'SIMPLE_AUTH_URL=http://172.18.0.1:' + config.get('simpleAuthPort'), // obsolete, remove + 'SIMPLE_AUTH_ORIGIN=http://172.18.0.1:' + config.get('simpleAuthPort'), 'SIMPLE_AUTH_CLIENT_ID=' + result.id ]; @@ -399,9 +370,9 @@ function setupLdap(app, options, callback) { assert.strictEqual(typeof callback, 'function'); var env = [ - 'LDAP_SERVER=172.17.0.1', + 'LDAP_SERVER=172.18.0.1', 'LDAP_PORT=' + config.get('ldapPort'), - 'LDAP_URL=ldap://172.17.0.1:' + config.get('ldapPort'), + 'LDAP_URL=ldap://172.18.0.1:' + config.get('ldapPort'), 'LDAP_USERS_BASE_DN=ou=users,dc=cloudron', 'LDAP_GROUPS_BASE_DN=ou=groups,dc=cloudron', 'LDAP_BIND_DN=cn='+ app.id + ',ou=apps,dc=cloudron', @@ -706,14 +677,15 @@ function setupRedis(app, options, callback) { if (!safe.fs.mkdirSync(redisDataDir) && safe.error.code !== 'EEXIST') return callback(new Error('Error creating redis data dir:' + safe.error)); const tag = infra.images.redis.tag, redisName = 'redis-' + app.id; - const cmd = `docker run --restart=always -d --name="${redisName}" \ - --hostname redis-${app.location}, \ + const cmd = `docker run --restart=always -d --name=${redisName} \ + --net cloudron \ + --net-alias ${redisName} \ -m 100m \ --memory-swap 150m \ -p 6379:6379 \ -v ${redisVarsFile}:/etc/redis/redis_vars.sh:ro \ -v ${redisDataDir}:/var/lib/redis:rw \ - --read-only -v /tmp -v /run "${tag}"`; + --read-only -v /tmp -v /run ${tag}`; var env = [ 'REDIS_URL=redis://redisuser:' + redisPassword + '@redis-' + app.id, @@ -723,6 +695,7 @@ function setupRedis(app, options, callback) { ]; async.series([ + // stop so that redis can flush itself with SIGTERM shell.execSync.bind(null, 'stopRedis', `docker stop --time=10 ${redisName} 2>/dev/null || true`), shell.execSync.bind(null, 'stopRedis', `docker rm --volumes ${redisName} 2>/dev/null || true`), shell.execSync.bind(null, 'startRedis', cmd), diff --git a/src/docker.js b/src/docker.js index e86a71715..b8a981291 100644 --- a/src/docker.js +++ b/src/docker.js @@ -133,7 +133,7 @@ function createSubcontainer(app, name, cmd, options, callback) { assert.strictEqual(typeof callback, 'function'); var docker = exports.connection, - isAppContainer = !cmd; + isAppContainer = !cmd; // non app-containers are like scheduler containers var manifest = app.manifest; var developmentMode = !!manifest.developmentMode; @@ -172,18 +172,14 @@ function createSubcontainer(app, name, cmd, options, callback) { // developerMode does not restrict memory usage memoryLimit = developmentMode ? 0 : memoryLimit; - // for subcontainers, this should ideally be false. but docker does not allow network sharing if the app container is not running - // this means cloudron exec does not work - var isolatedNetworkNs = true; - addons.getEnvironment(app, function (error, addonEnv) { if (error) return callback(new Error('Error getting addon environment : ' + error)); var containerOptions = { name: name, // used for filtering logs // do _not_ set hostname to app fqdn. doing so sets up the dns name to look up the internal docker ip. this makes curl from within container fail - // for subcontainers, this should not be set because we already share the network namespace with app container - Hostname: isolatedNetworkNs ? (semver.gte(targetBoxVersion(app.manifest), '0.0.77') ? app.location : config.appFqdn(app.location)) : null, + // Note that Hostname has no effect on DNS. We have to use the --net-alias for dns. Hostname cannot be set with container NetworkMode + Hostname: isAppContainer ? app.location : null, Tty: isAppContainer, Image: app.manifest.dockerImage, Cmd: (isAppContainer && developmentMode) ? [ '/bin/bash', '-c', 'echo "Development mode. Use cloudron exec to debug. Sleeping" && sleep infinity' ] : cmd, @@ -211,8 +207,7 @@ function createSubcontainer(app, name, cmd, options, callback) { }, CpuShares: 512, // relative to 1024 for system processes VolumesFrom: isAppContainer ? null : [ app.containerId + ":rw" ], - NetworkMode: isolatedNetworkNs ? 'default' : ('container:' + app.containerId), // share network namespace with parent - Links: isolatedNetworkNs ? addons.getLinksSync(app, app.manifest.addons) : null, // links is redundant with --net=container + NetworkMode: isAppContainer ? 'cloudron' : ('container:' + app.containerId), // share network namespace with parent SecurityOpt: config.CLOUDRON ? [ "apparmor:docker-cloudron-app" ] : null // profile available only on cloudron } }; diff --git a/src/infra_version.js b/src/infra_version.js index 5d0849160..1204105c4 100644 --- a/src/infra_version.js +++ b/src/infra_version.js @@ -11,7 +11,7 @@ exports = module.exports = { 'images': { 'mysql': { repo: 'cloudron/mysql', tag: 'cloudron/mysql:0.11.0' }, - 'postgresql': { repo: 'cloudron/postgresql', tag: 'cloudron/postgresql:0.10.0' }, + 'postgresql': { repo: 'cloudron/postgresql', tag: 'cloudron/postgresql:0.11.0' }, 'mongodb': { repo: 'cloudron/mongodb', tag: 'cloudron/mongodb:0.9.0' }, 'redis': { repo: 'cloudron/redis', tag: 'cloudron/redis:0.8.0' }, 'mail': { repo: 'cloudron/mail', tag: 'cloudron/mail:0.13.2' }, diff --git a/src/ldap.js b/src/ldap.js index c44e76ebe..f6006c696 100644 --- a/src/ldap.js +++ b/src/ldap.js @@ -265,7 +265,7 @@ function start(callback) { res.end(); }); - gServer.listen(config.get('ldapPort'), callback); + gServer.listen(config.get('ldapPort'), '0.0.0.0', callback); } function stop(callback) { diff --git a/src/platform.js b/src/platform.js index 42d77f228..1376dbfed 100644 --- a/src/platform.js +++ b/src/platform.js @@ -83,6 +83,8 @@ function startGraphite(callback) { const dataDir = paths.DATA_DIR; const cmd = `docker run --restart=always -d --name="graphite" \ + --net cloudron \ + --net-alias graphite \ -m 75m \ --memory-swap 150m \ -p 127.0.0.1:2003:2003 \ @@ -101,12 +103,14 @@ function startMysql(callback) { const dataDir = paths.DATA_DIR; const rootPassword = hat(256); - if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/mysql_vars.sh', - 'MYSQL_ROOT_PASSWORD=' + rootPassword +'\nMYSQL_ROOT_HOST=172.17.0.1', 'utf8')) { + if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/mysql_vars.sh', + 'MYSQL_ROOT_PASSWORD=' + rootPassword +'\nMYSQL_ROOT_HOST=172.18.0.1', 'utf8')) { return callback(new Error('Could not create mysql var file:' + safe.error.message)); } const cmd = `docker run --restart=always -d --name="mysql" \ + --net cloudron \ + --net-alias mysql \ -m 256m \ --memory-swap 512m \ -v "${dataDir}/mysql:/var/lib/mysql" \ @@ -128,6 +132,8 @@ function startPostgresql(callback) { } const cmd = `docker run --restart=always -d --name="postgresql" \ + --net cloudron \ + --net-alias postgresql \ -m 100m \ --memory-swap 200m \ -v "${dataDir}/postgresql:/var/lib/postgresql" \ @@ -149,6 +155,8 @@ function startMongodb(callback) { } const cmd = `docker run --restart=always -d --name="mongodb" \ + --net cloudron \ + --net-alias mongodb \ -m 100m \ --memory-swap 200m \ -v "${dataDir}/mongodb:/var/lib/mongodb" \ @@ -181,6 +189,8 @@ function startMail(callback) { if (error) return callback(error); const cmd = `docker run --restart=always -d --name="mail" \ + --net cloudron \ + --net-alias mail \ -m 75m \ --memory-swap 150m \ -e "MAIL_DOMAIN=${fqdn}" \ diff --git a/src/test/ldap-test.js b/src/test/ldap-test.js index 045360dbd..2b16a08d1 100644 --- a/src/test/ldap-test.js +++ b/src/test/ldap-test.js @@ -109,7 +109,7 @@ function setup(done) { IPAM: { Driver: "default", Config: [{ - Subnet: "172.17.0.0/16" + Subnet: "172.18.0.0/16" }] }, "Containers": {