2014-04-03 6 views
48

Ho il codice di tutti i miei siti web sotto /srv nei miei contenitori.Come modificare il codice in un contenitore Docker in fase di sviluppo?

My Dockerfile scarica il codice utilizzando git e lo rende parte dell'immagine per facilitare la distribuzione in produzione.

Ma come si modifica il codice in fase di sviluppo? Pensavo che usare i volumi fosse la soluzione, ad esempio: -v /docker/mycontainer/srv:/srv. Ma sovrascrive la directory nel contenitore. Se è la prima volta che lo eseguo, si svuota perché non c'è niente nell'host. Quindi qualsiasi cosa abbia fatto nel Dockerfile è andata persa.

Ci sono anche directory e file all'interno di /srv/myapp che voglio condividere tra le diverse versioni della mia app, ad esempio: /srv/myapp/user-uploads. Questo è uno common practice nello sviluppo web professionale.

Allora, cosa posso fare per essere in grado di fare tutte queste cose ?: codice

  • modificare in/srv nello sviluppo
  • parti/srv/frontend/user-arrivi attraverso diverse versioni
  • lasciare che Dockerfile scarichi il codice. Fare "git clone" o "git pull" al di fuori di Docker vanificherebbe lo scopo di Docker secondo me. Inoltre ci sono cose che non posso eseguire nell'host, come le migrazioni del database o altri script specifici dell'app.

C'è un modo per montare un volume inverso? Voglio dire rendere il contenitore sovrascrivere l'host, invece del contrario.

Penso che uno potrebbe essere quello di copiare/srv in /srv.deployment-copy prima di eseguire il daemon del contenitore. E poi quando eseguo il demone controlla se esiste /srv.deployment-copy e copia tutto in/srv. In questo modo posso usare/srv come volume ed essere ancora in grado di distribuire il codice con il Dockerfile. Sto già usando alias per tutti i comandi docker, quindi l'automazione di questo non sarà un problema. Cosa ne pensi?

+0

Memorizzare i dati utente nella cartella dell'app Web non è affatto una pratica comune. Complifica tutto senza una buona ragione. – rightfold

+1

Sì, fare git clone e git pull fuori da Docker è del tutto normale. È così che lo faccio. Il contenitore è solo un contenitore. Il codice dell'app cambia e viene tenuto in un repository separato. Le migrazioni e altri comandi specifici per app possono essere facilmente eseguiti utilizzando il comando exec che consente di eseguire comandi in un contenitore in esecuzione. – Kevin

risposta

9

Ho trovato il modo migliore per modificare il codice in fase di sviluppo è installare tutto come al solito (tra cui la clonazione repository della tua app), ma spostare tutto il codice nel contenitore per dire /srv/myapp.deploy.dev. Poi inizia il contenitore con un volume rw per /srv/myapp, e uno script init.d che pulisce quel volume e copia i nuovi contenuti all'interno del genere:

rm -r /srv/myapp/* 
rm -r /srv/myapp/.[!.]* 
cp -r /srv/myapp.deploy.dev/. /srv/myapp 
rm -r /srv/myapp.deploy.dev 
+4

Sto inciampando sullo stesso problema, sembra che tu l'abbia risolto ma non sono chiaro cosa stai facendo. Potresti elaborare la tua risposta con ciò che viene fatto nel Dockerfile (al momento della creazione dell'immagine) rispetto a ciò che viene fatto in alcuni script di avvio (al momento della creazione del contenitore)? – user779159

+3

@ user779159 Mi dispiace di essere stato lontano dal sito per mesi. Quello che sto facendo qui è spostare il codice da qualche altra parte prima di creare il volume, quindi creo il volume (sarà vuoto se è la prima volta, o con il vecchio codice se non lo è), quindi cancelli tutto nel volume (nel caso contiene il vecchio codice), quindi metto in esso il nuovo codice. Così ora ho il mio nuovo codice seduto in un volume, quindi posso modificarlo dall'esterno. – ChocoDeveloper

1

Supponendo che git non sia il punto di accesso del contenitore, se git è installato nel contenitore docker è possibile eseguire l'installazione di ssh nel contenitore ed eseguire git clone/git pull. A causa del modo in cui il volume è condiviso con l'host, le modifiche apportate dal contenitore ai file verranno apportate anche all'host (in realtà sono gli stessi file).

Here è una spiegazione di come ssh rapidamente in un contenitore.

+4

Posso ssh nel contenitore, ma farlo (git tirando * dopo * creando il contenitore) sconfigge lo scopo di Docker (o almeno la metà di esso) secondo me. Mi piacerebbe essere in grado di distribuire l'immagine come un pacchetto autonomo. Smettere di tirare dopo aver distribuito l'immagine non ha senso. Perderò anche la riproducibilità, l'immutabilità, la capacità di effettuare facilmente il rollback, ecc. Git pull è il tipo di cosa che potrebbe fallire per ragioni casuali e che l'uso della finestra mobile doveva risolvere. – ChocoDeveloper

+1

Sono d'accordo al 100%. Non ho ulteriori informazioni. –

+0

Ho postato la mia risposta, potrebbe essere utile. – ChocoDeveloper

5

Nota: non è possibile montare la directory del contenitore per ospitare la directory con -v.

Non penso che sia necessario modificare/srv e /srv.deployment-copy. Se

penso che:

  • si dovrebbe usare il volume per i dati persistenti/comune: -v /hostdir/user-uploads:/srv/myapp/user-uploads, oppure è possibile utilizzare data volume container concetto. È possibile considerare questo un database con supporto del file system che viene archiviato nell'host (contenitore solo dati) e il contenitore può utilizzarlo entro il -v.

  • Lei ha ragione: per la distribuzione produzione - si può costruire l'immagine con il codice sorgente (git clone), si crea un'immagine per ogni rilascio. Non dovrebbe essere necessario modificare il codice sorgente in produzione.

  • per ambiente di sviluppo - è necessario creare l'immagine senza codice sorgente oppure è possibile ombreggiare la directory del codice sorgente con volume in caso di utilizzo della stessa immagine per implementazione/sviluppo. Quindi digita il codice sorgente clone localmente e utilizza il volume -v /hostdir/project/src:/srv/project per condividere il codice sorgente con il contenitore. Preferibilmente dovresti condividere il codice sorgente in sola lettura (:ro alla fine) e qualsiasi file temporaneo o intermedio dovrebbe essere archiviato da qualche altra parte nel contenitore. Ho degli script di configurazione (migrazione dei dati, ricostruzione di alcuni file di dati di indice/cache, ecc.) Eseguiti all'avvio del contenitore, prima dell'avvio del servizio. Quindi, ogni volta che sento che ho bisogno di un nuovo re-init, ho appena finito di uccidere il contenitore dev ed eseguirlo di nuovo. Oppure, non fermo il vecchio contenitore: ne gestisco un altro.

10

C'è un altro modo per iniziare contenitore con volumi da un altro contenitore:

Guarda https://docs.docker.com/userguide/dockervolumes/
Creazione e montaggio di un contenitore di volume dati

Se si dispone di alcuni dati persistenti che Y vuoi condividere tra contenitori, o vuoi usare da contenitori non persistenti, è meglio creare un contenitore del volume di dati con nome e poi montare i dati da esso.

Creiamo un nuovo contenitore denominato con un volume da condividere.

$ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres 

È quindi possibile utilizzare il flag --volumes-from per montare il volume/dbdata in un altro contenitore.

$ sudo docker run -d --volumes-from dbdata --name db1 training/postgres 

E un altro:

$ sudo docker run -d --volumes-from dbdata --name db2 training/postgres 

Un'altra utile funzione possiamo eseguire con volumi è usarle per i backup, ripristini e migrazioni. Lo facciamo utilizzando i --volumes-da bandiera per creare un nuovo contenitore che monta quel volume, in questo modo:

$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata 

=============

I pensa che non dovresti usare il montaggio della tua directory host in un contenitore. Ma puoi usare i volumi con tutti i suoi poteri. È possibile modificare i file in volumi utilizzando altri contenitori con set perfetto di editor e strumenti. E contenitore questa tua app sarà pulita senza sovraccarico.

Struttura è:
-) Contenitore per i dati app
docker run -d -v /data --name data
-) Contenitore per i binari app
docker run -d --volumes-from data --name app1
-) Contenitore per editor e utilità per lo sviluppo
docker run -d --volumes-from data --name editor

5

ho trovato un bel modo di farlo usando solo git:

CONTAINER=my_container 
SYNC_REPO=/tmp/my.git 
CODE=/var/www 

#create bare repo in container 
docker exec $CONTAINER git init --bare $SYNC_REPO 

#add executable syncing hook that checks out into code dir in container 
printf "#!/bin/sh\nGIT_WORK_TREE=$CODE git checkout -f\n" | \ 
docker exec -i $CONTAINER bash -c "tee $SYNC_REPO/hooks/post-receive;chmod +x \$_" 

#use git-remote-helper to use docker exec instead of ssh for git 
git remote add docker "ext::docker exec -i $CONTAINER sh -c %S% $SYNC_REPO" 

#push updated local code into docker 
git push docker master 

Si suppone di avere un git locale con il codice. Git deve essere installato nel contenitore. In alternativa potresti probabilmente usare docker run e un contenitore di dati con un volume condiviso con git installato.