UNPKG

4.72 kBJavaScriptView Raw
1const chalk = require( 'chalk' );
2const sh = require( 'shelljs' );
3const util = require( './util' );
4const config = require( './config' );
5
6const docker = {
7
8 /**
9 * Check if docker is available.
10 * @return {Boolean}
11 */
12 isAvailable() {
13 const isNotReachable = sh.exec( '(docker ps -q || printf true)', { silent: true });
14
15 if ( isNotReachable.stdout === 'true' ) {
16 return false;
17 }
18
19 return true;
20 },
21
22 /**
23 * Exit program if docker daemon is not running.
24 * @return {String}
25 */
26 check() {
27 if ( !this.isAvailable() ) {
28 console.log( chalk`{red It doesn't look like you have Docker running.}` );
29 process.exit( 1 );
30 }
31 },
32
33 /**
34 * Build the string to be used as the docker run shell command.
35 * https: //docs.docker.com/engine/reference/commandline/run/
36 * @param {String} slug The project's slug.
37 * @param {String} url The project's url.
38 * @param {Object} container
39 * @return {String}
40 */
41 buildRunCmd( slug, url, container ) {
42 const errors = [];
43
44 const cmdParts = [
45 'docker run',
46 '-d',
47 ];
48
49 // Add hostname reference.
50 if ( this.checkForOption( container.database ) ) {
51 // Database hostname.
52 } else {
53 // Web server hostname.
54 const hostname = util.getProjectHostname( url );
55 cmdParts.push( `-h ${hostname}` );
56 }
57
58 // Assign a name to the container.
59 if ( this.checkForOption( container.database ) ) {
60 cmdParts.push( `--name ${slug}_db` );
61 } else {
62 cmdParts.push( `--name ${slug}` );
63 }
64
65 // Set environment variables.
66 if ( this.checkForOption( container.env_variables ) ) {
67 cmdParts.push( `-e ${container.env_variables.join( ' -e ' )}` );
68 }
69
70 // Bind mount a volume.
71 if ( this.checkForOption( container.volumes ) ) {
72 cmdParts.push( `-v ${container.volumes.join( ' -v ' )}` );
73 }
74
75 // Expose a port or a range of ports.
76 if ( this.checkForOption( container.expose ) ) {
77 cmdParts.push( `-p ${container.expose}` );
78 }
79
80 // Add link to another container.
81 if ( !this.checkForOption( container.database ) && this.checkForOption( container.link ) ) {
82 cmdParts.push( `--link ${container.link}` );
83 }
84
85 // Container name.
86 if ( this.checkForOption( container.image ) ) {
87 cmdParts.push( container.image );
88 } else {
89 errors.push( chalk`Cannot find docker image.` );
90 }
91
92 // Report any errors.
93 if ( errors.length ) {
94 errors.forEach( ( error ) => {
95 console.log( chalk`{red Error:} ${error}` );
96 });
97 process.exit( 1 );
98 }
99
100 const cmd = cmdParts.join( ' ' );
101
102 return cmd;
103 },
104
105 /**
106 * Build the string to be ran from inside the docker container after creation.
107 * @param {String} slug The project's slug.
108 * @param {Object} container
109 * @return {String}
110 */
111 buildContainerCmd( slug, container ) {
112 const cmd = `docker exec ${slug} bash -c '${container.after_run_container_cmd}'`;
113
114 return cmd;
115 },
116
117 /**
118 * Check if option exists.
119 * @param {String|Object} option
120 * @return {Boolean}
121 */
122 checkForOption( option ) {
123 let optionExists = true;
124
125 if ( typeof option === 'object' && util.isEmptyObject( option ) ) {
126 optionExists = false;
127 }
128
129 if ( option === undefined || typeof option === 'undefined' ) {
130 optionExists = false;
131 }
132
133 return optionExists;
134 },
135
136 /**
137 * Setup selected project type.
138 * @param {String} slug The project's slug.
139 * @param {String} url The project's url.
140 * @param {Object} typeInfo The project's type info.
141 */
142 setup( slug, url, typeInfo ) {
143 const { containers } = typeInfo;
144 const containerNames = [];
145
146 containers.forEach( ( container ) => {
147 // Get the latest container image.
148 if ( this.checkForOption( container.image ) ) {
149 sh.exec( `docker pull ${container.image}` );
150 } else {
151 console.log( chalk`{red Error: Docker image is not defined.` );
152 process.exit( 1 );
153 }
154
155 const runCmd = this.buildRunCmd( slug, url, container );
156
157 let containerName;
158
159 if ( this.checkForOption( container.database ) ) {
160 containerName = `${slug}_db`;
161 } else {
162 containerName = `${slug}`;
163 }
164
165 let containerCmd = null;
166
167 if ( this.checkForOption( container.after_run_container_cmd ) ) {
168 containerCmd = this.buildContainerCmd( slug, container );
169 }
170
171 // Primary command for project type's docker container.
172 console.log( chalk`{blue ${runCmd}}` );
173 sh.exec( runCmd );
174
175 // Secondary command for project type's docker container if needed..
176 if ( containerCmd !== null ) {
177 console.log( chalk`{blue ${containerCmd}}` );
178 sh.exec( containerCmd );
179 }
180
181 // Restart docker if needed.
182 if ( container.restart ) {
183 sh.exec( `docker restart ${containerName}` );
184 }
185
186 containerNames.push( containerName );
187 });
188
189 config.updateContainerNames( slug, containerNames );
190 },
191
192};
193
194module.exports = docker;