├── .gitignore
├── .gitmodules
├── DropdockRoboFile.php
├── README.md
├── Robofile.php
├── composer.json
├── docker-compose.yml.dist
├── dropdock
└── php-src
└── DropdockRunner.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /bin
2 | dropdock.phar
3 | /data
4 | docker-compose.yml
5 | docker-compose.yml.dev
6 | src/github-repos
7 | vendor
8 | composer.lock
9 | tmp
10 | .vagrant
11 | Vagrantfile
12 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src"]
2 | path = src
3 | url = git@github.com:twinbit/dropdock-containers.git
4 |
--------------------------------------------------------------------------------
/DropdockRoboFile.php:
--------------------------------------------------------------------------------
1 | yell("Dropdock init.");
30 | $base_path = $this->getBasePath();
31 |
32 | // Create directory structure.
33 | $this->taskFileSystemStack()
34 | ->mkdir('data')
35 | ->mkdir('bin')
36 | ->run();
37 |
38 | // Create static binaries.
39 | $this->createBinaries();
40 |
41 | // Make binaries executables.
42 | $this->taskExec('chmod -R +x bin')->run();
43 |
44 | // Rename fig.yml.dist to docker-compose.yml
45 | $this->taskFileSystemStack()
46 | ->copy($base_path . '/docker-compose.yml.dist', 'docker-compose.yml')
47 | ->run();
48 | $uid = trim($this->taskExec('id -u')->run()->getMessage());
49 | $gid = trim($this->taskExec('id -g')->run()->getMessage());
50 | $this->taskReplaceInFile('docker-compose.yml')
51 | ->from('##LOCAL_UID##')
52 | ->to($uid)
53 | ->run();
54 | $this->taskReplaceInFile('docker-compose.yml')
55 | ->from('##LOCAL_GID##')
56 | ->to($gid)
57 | ->run();
58 | }
59 |
60 | /**
61 | * Recreate containers binaries.
62 | */
63 | public function createBinaries()
64 | {
65 | $yaml = new Parser();
66 | $base_path = $this->getBasePath();
67 | $cwd = getcwd();
68 | $files = Finder::create()->ignoreVCS(true)
69 | ->files()
70 | ->name('binaries.yml')
71 | ->in(__DIR__);
72 | foreach ($files as $file) {
73 | $binaries = $yaml->parse(file_get_contents($base_path . '/' . $file->getRelativePathname()));
74 | foreach ($binaries as $container => $binaries) {
75 | foreach ($binaries as $bin => $opts) {
76 | $this->taskWriteToFile("bin/{$bin}")
77 | ->line(isset($opts['env']) ? $opts['env'] : '#!/usr/bin/env bash')
78 | ->line("cd {$cwd} && docker-compose run --rm {$container} {$opts['bin']} {$opts['arguments']}")
79 | ->run();
80 | }
81 | }
82 | }
83 | }
84 |
85 | /**
86 | * Symlink www and bin folders.
87 | */
88 | public function symlink()
89 | {
90 | $this->taskFileSystemStack()
91 | ->symlink('data/var/www', 'www')
92 | ->run();
93 | }
94 |
95 | /**
96 | * Reconfigure boot2docker cpu/memory.
97 | */
98 | public function boot2dockerOptimize($opts = ['cpu' => '1', 'memory' => '8192'])
99 | {
100 | $memory = $opts['memory'];
101 | $cpu = $opts['cpu'];
102 | $this->taskExecStack()
103 | ->stopOnFail(TRUE)
104 | ->exec('boot2docker stop')
105 | ->exec('VBoxManage modifyvm "boot2docker-vm" --memory ' . $memory . ' --cpus ' . $cpu)
106 | ->exec('boot2docker up')
107 | ->run();
108 | }
109 |
110 | /**
111 | * Configure NFS mount boot script.
112 | *
113 | * @todo this task needs to be explained better (fe: howto configure nfs exports locally).
114 | */
115 | public function boot2dockerNfsSetup()
116 | {
117 | $base_path = $this->getBasePath();
118 | $mount_boot_script = file_get_contents($base_path . '/src/scripts/boot2local.sh');
119 | $this->taskExecStack()
120 | ->stopOnFail(FALSE)
121 | ->exec('boot2docker ssh "sudo rm -f /var/lib/boot2docker/bootlocal.sh && sudo touch /var/lib/boot2docker/bootlocal.sh"')
122 | ->exec('boot2docker ssh "echo \'' . $mount_boot_script . '\' | sudo tee -a /var/lib/boot2docker/bootlocal.sh" >/dev/null')
123 | ->exec('boot2docker ssh "sudo chmod +x /var/lib/boot2docker/bootlocal.sh" > /dev/null')
124 | ->exec('boot2docker restart')
125 | ->run();
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dropdock
2 |
3 | ## Installing
4 |
5 | ### Phar
6 |
7 | [Download dropdock.phar >](http://twinbit.github.io/dropdock/dropdock.phar)
8 |
9 | ```
10 | wget http://twinbit.github.io/dropdock/dropdock.phar
11 | ```
12 |
13 | To install globally put `dropdock.phar` in `/usr/bin`.
14 |
15 | ```
16 | sudo chmod +x dropdock.phar && sudo mv dropdock.phar /usr/bin/dropdock
17 | ```
18 |
19 | Now you can use it just like `dropdock`.
20 |
21 | ## Usage
22 |
23 | Just run `dropdock init` in a empty folder to bootstrap a new dropdock project:
24 |
25 | ```
26 | |-- bin
27 | | |-- cli
28 | | |-- drush
29 | | |-- mysql
30 | | |-- mysql_cli
31 | | |-- mysql_create
32 | | |-- mysql_import
33 | | |-- phing
34 | | `-- phpcs
35 | |-- data
36 | `-- fig.yml
37 | ```
38 |
39 | (@TODO) Tweak `fig.yml` to match your needs and run `fig up -d` to run the containers.
40 | At the first run fig will download and build remote containers, it can takes several minutes.
41 |
42 |
43 | ## Boot2docker configuration steps:
44 |
45 | In order to not going insane trying to fix vboxfs shared folder permissions, it is better to
46 | use NFS from OSX in order to have an automatic mapping to local user uid/gid:
47 |
48 | ### OSX NFS Export
49 |
50 | Edit your /etc/exports file as follows:
51 |
52 | ```
53 | /Users -mapall=youruser:staff boot2docker
54 | ```
55 |
56 | ### Booot2docker configuration
57 |
58 | ```
59 | boot2docker ssh
60 | sudo umount /Users
61 | sudo /usr/local/etc/init.d/nfs-client start
62 | # See http://www.slashroot.in/how-do-linux-nfs-performance-tuning-and-optimization
63 | # See http://www.gossamer-threads.com/lists/wiki/mediawiki-cvs/500057
64 | sudo mount 192.168.59.3:/Users /Users -o rw,async,noatime,rsize=32768,wsize=32768,proto=tcp
65 | ```
66 |
67 | ## Sublime text NFS bug
68 |
69 | If you are using SublimeText, you could experience this problem: https://github.com/mitchellh/vagrant/issues/2768:
70 | `NFS not updating files if the file length stayed the same.`
71 |
72 | To fix it: Sublime Text > Preferences > Settings- User
73 |
74 | ```
75 | {
76 | "atomic_save": false
77 | }
78 | ```
79 |
80 | ## TODO
81 |
82 | - Move boot2local nfs configurations out of https://github.com/twinbit/dropdock-containers repository
83 | - Refactor dropdockRoboFile::boot2dockerNfsSetup() to handle better mount.nfs "fsc" options (Related to cachefilesd)
84 | - Create a custom iso tu automatically run the cachefilesd repository
85 |
86 | ```
87 | FROM ubuntu:14.04
88 | MAINTAINER Paolo Mainardi "paolo@twinbit.it"
89 | ENV UPDATE_AT 1
90 | RUN apt-get update && apt-get -y install cachefilesd
91 | CMD /sbin/cachefilesd -n -f /etc/cachefilesd.conf -s
92 | ```
93 |
--------------------------------------------------------------------------------
/Robofile.php:
--------------------------------------------------------------------------------
1 | yell("Releasing Dropdock");
15 | $this->taskExecStack()
16 | ->stopOnFail()
17 | ->exec("git submodule update --init --recursive --remote")
18 | ->run();
19 | $this->taskGitStack()
20 | ->add('-A')
21 | ->commit("auto-update")
22 | ->pull()
23 | ->push()
24 | ->run();
25 | $this->taskGitHubRelease(\Twinbit\DropdockRunner::VERSION)
26 | ->uri('twinbit/dropdock')
27 | ->askDescription()
28 | ->run();
29 | $this->pharPublish();
30 | $this->versionBump();
31 | }
32 |
33 | /**
34 | * Build the Dropdock phar package
35 | */
36 | public function pharBuild()
37 | {
38 | $yaml = new Parser();
39 | $packer = $this->taskPackPhar('dropdock.phar');
40 | // $packer->compress(TRUE);
41 | $this->taskComposerInstall()
42 | ->noDev()
43 | ->printed(false)
44 | ->run();
45 |
46 | // Add php sources.
47 | $files = Finder::create()->ignoreVCS(true)
48 | ->files()
49 | ->name('*.php')
50 | ->path('php-src')
51 | ->path('vendor')
52 | ->notPath('data')
53 | ->notPath('tmp')
54 | ->in(__DIR__);
55 | foreach ($files as $file) {
56 | $packer->addFile($file->getRelativePathname(), $file->getRealPath());
57 | }
58 |
59 | // Add binaries yaml config.
60 | $files = Finder::create()->ignoreVCS(true)
61 | ->files()
62 | ->name('binaries.yml')
63 | ->in(__DIR__);
64 | foreach ($files as $file) {
65 | $packer->addFile($file->getRelativePathname(), $file->getRealPath());
66 | }
67 |
68 | // Add dropdock binary and make it as executable.
69 | $packer->addFile('DropdockRoboFile.php', 'DropdockRoboFile.php');
70 | // Add docker-compose.yml.
71 | $packer->addFile('docker-compose.yml.dist', 'docker-compose.yml.dist');
72 |
73 | // Add boot2local.sh script.
74 | $packer->addFile('src/scripts/boot2local.sh', 'src/scripts/boot2local.sh');
75 |
76 | $packer->addFile('dropdock', 'dropdock')
77 | ->executable('dropdock')
78 | ->run();
79 | $this->taskComposerInstall()
80 | ->printed(false)
81 | ->run();
82 | }
83 |
84 | public function pharPublish()
85 | {
86 | $this->pharBuild();
87 | rename('dropdock.phar', 'dropdock-release.phar');
88 | $this->taskGitStack()->checkout('gh-pages')->run();
89 | rename('dropdock-release.phar', 'dropdock.phar');
90 | $this->taskGitStack()
91 | ->add('dropdock.phar')
92 | ->commit('dropdock.phar published')
93 | ->push('origin','gh-pages')
94 | ->checkout('master')
95 | ->run();
96 | }
97 |
98 | public function versionBump($version = null)
99 | {
100 | if (!$version) {
101 | $versionParts = explode('.', \Twinbit\dropdockRunner::VERSION);
102 | $versionParts[count($versionParts)-1]++;
103 | $version = implode('.', $versionParts);
104 | }
105 | $this->taskReplaceInFile(__DIR__.'/php-src/DropdockRunner.php')
106 | ->from("VERSION = '".\Twinbit\dropdockRunner::VERSION."'")
107 | ->to("VERSION = '".$version."'")
108 | ->run();
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twinbit/dropdock",
3 | "description": "Drupal docker environment",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Paolo Mainardi",
8 | "email": "paolo.mainardi@sparkfabrik.com"
9 | }
10 | ],
11 | "bin":["dropdock"],
12 | "autoload":{
13 | "psr-4":{
14 | "Twinbit\\":"php-src"
15 | }
16 | },
17 | "require": {
18 | "php": ">=5.4.0",
19 | "codegyre/robo": "*",
20 | "symfony/yaml": "*"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/docker-compose.yml.dist:
--------------------------------------------------------------------------------
1 | data:
2 | image: twinbit/docker-drupal-data
3 | hostname: data
4 | volumes:
5 | - data:/data
6 | nginx:
7 | image: twinbit/docker-drupal-nginx
8 | hostname: nginx
9 | environment:
10 | - LOCAL_UID=##LOCAL_UID##
11 | - LOCAL_GID=##LOCAL_GID##
12 | links:
13 | - php
14 | volumes_from:
15 | - data
16 | ports:
17 | - "8000:80"
18 | privileged: true
19 | php:
20 | image: twinbit/docker-drupal-php
21 | hostname: php
22 | links:
23 | - mysql
24 | - mailcatcher
25 | - solr
26 | volumes_from:
27 | - data
28 | privileged: true
29 | cli:
30 | image: twinbit/docker-drupal-cli
31 | hostname: cli
32 | environment:
33 | - LOCAL_UID=##LOCAL_UID##
34 | - LOCAL_GID=##LOCAL_GID##
35 | - COMPOSER_CACHE_DIR=/composer-cache
36 | links:
37 | - mysql
38 | - mailcatcher
39 | - solr
40 | volumes_from:
41 | - data
42 | volumes:
43 | - data/var/apps/drush:/home/www-data/.drush
44 | - data/var/cache/composer:/composer-cache
45 | # Add ssh keys to container in order to download private repos.
46 | - data/ssh-keys:/home/www-data/.ssh
47 | privileged: true
48 | mysql:
49 | image: twinbit/docker-drupal-mysql
50 | hostname: mysql
51 | privileged: true
52 | ports:
53 | - "3306:3306"
54 | volumes_from:
55 | - data
56 | mailcatcher:
57 | image: twinbit/docker-drupal-mailcatcher
58 | hostname: mailcatcher
59 | volumes_from:
60 | - data
61 | ports:
62 | - "1080:1080"
63 | solr:
64 | image: twinbit/docker-drupal-solr
65 | hostname: solr
66 | ports:
67 | - "8983:8983"
68 | command: -Xmx1024m -DSTOP.PORT=8079 -DSTOP.KEY=stopkey -jar start.jar
69 |
70 |
71 |
--------------------------------------------------------------------------------
/dropdock:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | execute();
20 |
--------------------------------------------------------------------------------
/php-src/DropdockRunner.php:
--------------------------------------------------------------------------------
1 | writeln(" ".self::ROBOFILE." not found in this dir ");
29 | exit;
30 | }
31 | require_once $conf_file;
32 | if (!class_exists(self::ROBOCLASS)) {
33 | $this->writeln("Class ".self::ROBOCLASS." was not loaded");
34 | return false;
35 | }
36 | return true;
37 | }
38 |
39 | public function execute()
40 | {
41 | register_shutdown_function(array($this, 'shutdown'));
42 | $app = new Application('Dropdock', self::VERSION);
43 |
44 | $loaded = $this->loadRoboFile();
45 | if (!$loaded) {
46 | $app->add(new Init('init'));
47 | $app->run();
48 | return;
49 | }
50 | $input = $this->prepareInput();
51 |
52 | $className = self::ROBOCLASS;
53 | $roboTasks = new $className;
54 | $taskNames = array_filter(get_class_methods(self::ROBOCLASS), function($m) {
55 | return !in_array($m, ['__construct']);
56 | });
57 | $passThrough = $this->passThroughArgs;
58 | foreach ($taskNames as $taskName) {
59 | $command = $this->createCommand($taskName);
60 | $command->setCode(function(InputInterface $input) use ($roboTasks, $taskName, $passThrough) {
61 | // get passthru args
62 | $args = $input->getArguments();
63 | array_shift($args);
64 | if ($passThrough) {
65 | $args[key(array_slice($args, -1, 1, TRUE))] = $passThrough;
66 | }
67 | $args[] = $input->getOptions();
68 | $res = call_user_func_array([$roboTasks, $taskName], $args);
69 | if (is_int($res)) exit($res);
70 | if (is_bool($res)) exit($res ? 0 : 1);
71 | if ($res instanceof Result) exit($res->getExitCode());
72 | });
73 | $app->add($command);
74 | }
75 | $app->run($input);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------