Они очень дополняют друг друга.
Я использовал комбинацию VirtualBox, Vagrant и Docker для всех своих проектов в течение нескольких месяцев и почувствовал следующие преимущества.
В Vagrant вы можете полностью отказаться от любой индивидуальной подготовки Chef, и все, что вам нужно, чтобы ваш файл vagrant, это подготовить машину, которая запускает один небольшой сценарий оболочки, который устанавливает Docker. Это означает, что мои Vagrant-файлы для каждого проекта практически идентичны и очень просты.
Вот типичный Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "mark2"
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
[3000, 5000, 2345, 15672, 5672, 15674, 27017, 28017, 9200, 9300, 11211, 55674, 61614, 55672, 5671, 61613].each do |p|
config.vm.network :forwarded_port, guest: p, host: p
end
config.vm.network :private_network, ip: "192.168.56.20"
config.vm.synced_folder ".", "/vagrant", :type => "nfs"
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", "2048"]
vb.customize ["modifyvm", :id, "--cpus", "2"]
end
# Bootstrap to Docker
config.vm.provision :shell, path: "script/vagrant/bootstrap", :privileged => true
# Build docker containers
config.vm.provision :shell, path: "script/vagrant/docker_build", :privileged => true
# Start containers
# config.vm.provision :shell, path: "script/vagrant/docker_start", :privileged => true
end
Файл Bootstrap, который устанавливает Docker, выглядит следующим образом
#!/usr/bin/env bash
echo 'vagrant ALL= (ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers
apt-get update -y
apt-get install htop -y
apt-get install linux-image-extra-`uname -r` -y
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list
apt-get update -y
apt-get install lxc-docker -y
apt-get install curl -y
Теперь, чтобы получить все необходимые мне службы, у меня есть скрипт docker_start, который выглядит примерно так
#!/bin/bash
cd /vagrant
echo Starting required service containers
export HOST_NAME=192.168.56.20
# Start MongoDB
docker run --name=mongodb --detach=true --publish=27017:27017 --publish=28017:28017 dockerfile/mongodb
read -t5 -n1 -r -p "Waiting for mongodb to start..." key
# Start rabbitmq
docker run --name=rabbitmq --detach=true --publish=5671:5671 --publish=5672:5672 --publish=55672:55672 --publish=15672:15672 --publish=15674:15674 --publish=61613:61613 --env RABBITMQ_USER=guest --env RABBITMQ_PASS=guest rabbitmq
read -t5 -n1 -r -p "Waiting for rabbitmq to start..." key
# Start cache
docker run --name=memcached --detach=true --publish=11211:11211 ehazlett/memcached
read -t5 -n1 -r -p "Waiting for cache to start..." key
# Start elasticsearch
docker run --name=elasticsearch --detach=true --publish=9200:9200 --publish=9300:9300 dockerfile/elasticsearch
read -t5 -n1 -r -p "Waiting for elasticsearch to start..." key
echo "All services started"
В этом примере я использую MongoDB, Elastisearch, RabbitMQ и Memcached
Конфигурация соло Chef без докера будет значительно сложнее.
Последний большой плюс получается, когда вы переходите в производственную среду, перевод среды разработки в инфраструктуру хостов, которые одинаковы в том смысле, что у них достаточно конфигурации, чтобы запустить докер, означает очень небольшую работу.
Если вам интересно, у меня есть более подробная статья о среде разработки на моем собственном веб-сайте по адресу
Вызов libc stdio printf
, реализация int main () {return printf (message); }
; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits. It needs to be linked with a C library.
; ----------------------------------------------------------------------------
global _main
extern _printf
section .text
_main:
push message
call _printf
add esp, 4
ret
message:
db 'Hello, World', 10, 0
Затем запустите
nasm -fwin32 helloworld.asm
gcc helloworld.obj
a
Там также The Clueless Newbies Guide to Hello World in Nasm без использования библиотеки C. Тогда код будет выглядеть так:
16-битный код с системными вызовами MS-DOS: работает в эмуляторах DOS или в 32-битной Windows с поддержкой NTVDM . Невозможно запустить "напрямую" (прозрачно) под любой 64-битной Windows, потому что ядро x86-64 не может использовать режим vm86.
org 100h
mov dx,msg
mov ah,9
int 21h
mov ah,4Ch
int 21h
msg db 'Hello, World!',0Dh,0Ah,'$'
Встраивайте его в исполняемый файл .com
, чтобы он быть загруженным в cs: 100h
со всеми сегментными регистрами, равными друг другу (модель крошечной памяти).
Удачи.
Если вы не вызываете некоторую функцию, этого нет в все банально. (И, серьезно, нет реальной разницы в сложности между вызовом printf и вызовом функции api win32.)
Даже DOS int 21h на самом деле просто вызов функции, даже если это другой API.
Если вы хотите делать это без посторонней помощи вам нужно напрямую общаться с видеооборудованием, вероятно, записывая растровые изображения букв «Hello world» во фреймбуфер. Даже тогда видеокарта выполняет работу по преобразованию этих значений памяти в сигналы VGA / DVI.
Обратите внимание, что, на самом деле, ничто из этого, вплоть до аппаратного обеспечения, в ASM не интереснее, чем в C. A Программа "hello world" сводится к вызову функции. В ASM есть одна приятная особенность: вы можете довольно легко использовать любой ABI; вам просто нужно знать, что это за ABI.
В этом примере показано, как перейти непосредственно к Windows API, а не ссылаться на стандартную библиотеку C.
global _main
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
push -11
call _GetStdHandle@4
mov ebx, eax
; WriteFile( hstdOut, message, length(message), &bytes, 0);
push 0
lea eax, [ebp-4]
push eax
push (message_end - message)
push message
push ebx
call _WriteFile@20
; ExitProcess(0)
push 0
call _ExitProcess@4
; never here
hlt
message:
db 'Hello, World', 10
message_end:
Для компиляции вам потребуются NASM и LINK.EXE (из Visual Studio Standard Edition)
nasm -fwin32 hello.asm link /subsystem:console /nodefaultlib /entry:main hello.obj
Это примеры Win32 и Win64 с использованием вызовов Windows API. Они предназначены для MASM, а не для NASM, но взгляните на них. Вы можете найти более подробную информацию в этой статье.
Здесь используется MessageBox вместо вывода на стандартный вывод.
;---ASM Hello World Win32 MessageBox
.386
.model flat, stdcall
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
title db 'Win32', 0
msg db 'Hello World', 0
.code
Main:
push 0 ; uType = MB_OK
push offset title ; LPCSTR lpCaption
push offset msg ; LPCSTR lpText
push 0 ; hWnd = HWND_DESKTOP
call MessageBoxA
push eax ; uExitCode = MessageBox(...)
call ExitProcess
End Main
;---ASM Hello World Win64 MessageBox
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
.data
title db 'Win64', 0
msg db 'Hello World!', 0
.code
main proc
sub rsp, 28h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, msg ; LPCSTR lpText
lea r8, title ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA
add rsp, 28h
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
main endp
End
Чтобы собрать и связать их с помощью MASM, используйте этот для 32-битного исполняемого файла:
ml.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main
или это для 64-битного исполняемого файла:
ml64.exe [filename] /link /subsystem:windows
/defaultlib:kernel32.lib /defaultlib:user32.lib /entry:main